题意:多次询问区间[l,r]中不是lca(xl...xr)的数的个数
先用线段树找出区间lca,然后用可持久化trie统计区间中是lca的数有多少个
1 #include<stdio.h> 2 #define loga 29 3 int tot,M,Tgcd[300000],root[100010],ch[4000000][2],size[4000000]; 4 int gcd(int a,int b){ 5 if(a==0){ 6 if(b==0)return 0; 7 return b; 8 } 9 if(b==0)return a; 10 if(a%b==0)return b; 11 return gcd(b,a%b); 12 } 13 int querygcd(int s,int t){ 14 int ans=Tgcd[s+M]; 15 for(s+=M-1,t+=M+1;s^t^1;s>>=1,t>>=1){ 16 if(~s&1)ans=gcd(ans,Tgcd[s^1]); 17 if(t&1)ans=gcd(ans,Tgcd[t^1]); 18 } 19 return ans; 20 } 21 void insert(int lroot,int rroot,int v,int p){ 22 size[rroot]=size[lroot]+1; 23 if(p<0)return; 24 ch[rroot][((v>>p)&1)^1]=ch[lroot][((v>>p)&1)^1]; 25 tot++; 26 ch[rroot][(v>>p)&1]=tot; 27 insert(ch[lroot][(v>>p)&1],ch[rroot][(v>>p)&1],v,p-1); 28 } 29 int querynum(int lroot,int rroot,int v,int p){ 30 if(p<0)return size[rroot]-size[lroot]; 31 if(ch[rroot][(v>>p)&1]==0)return 0; 32 return querynum(ch[lroot][(v>>p)&1],ch[rroot][(v>>p)&1],v,p-1); 33 } 34 int main(){ 35 int n,m,i,j; 36 scanf("%d",&n); 37 for(M=1;M<n+2;M<<=1); 38 for(i=1;i<=n;i++){ 39 scanf("%d",Tgcd+M+i); 40 tot++; 41 root[i]=tot; 42 insert(root[i-1],root[i],Tgcd[M+i],loga); 43 } 44 for(i=M-1;i>0;i--)Tgcd[i]=gcd(Tgcd[i<<1],Tgcd[i<<1|1]); 45 scanf("%d",&m); 46 while(m--){ 47 scanf("%d%d",&i,&j); 48 printf("%d\n",j-i+1-querynum(root[i-1],root[j],querygcd(i,j),loga)); 49 } 50 }
时间: 2024-10-23 01:00:01