您的位置:首页 > 其它

[CF474F] Ant colony

2017-08-19 21:25 204 查看
题意:多次询问区间$[l,r]$中不是$gcd(x_l\cdots x_r)$的数的个数

先用线段树找出区间gcd,然后用可持久化trie统计区间中是gcd的数有多少个

#include<stdio.h>
#define loga 29
int tot,M,Tgcd[300000],root[100010],ch[4000000][2],size[4000000];
int gcd(int a,int b){
if(a==0){
if(b==0)return 0;
return b;
}
if(b==0)return a;
if(a%b==0)return b;
return gcd(b,a%b);
}
int querygcd(int s,int t){
int ans=Tgcd[s+M];
for(s+=M-1,t+=M+1;s^t^1;s>>=1,t>>=1){
if(~s&1)ans=gcd(ans,Tgcd[s^1]);
if(t&1)ans=gcd(ans,Tgcd[t^1]);
}
return ans;
}
void insert(int lroot,int rroot,int v,int p){
size[rroot]=size[lroot]+1;
if(p<0)return;
ch[rroot][((v>>p)&1)^1]=ch[lroot][((v>>p)&1)^1];
tot++;
ch[rroot][(v>>p)&1]=tot;
insert(ch[lroot][(v>>p)&1],ch[rroot][(v>>p)&1],v,p-1);
}
int querynum(int lroot,int rroot,int v,int p){
if(p<0)return size[rroot]-size[lroot];
if(ch[rroot][(v>>p)&1]==0)return 0;
return querynum(ch[lroot][(v>>p)&1],ch[rroot][(v>>p)&1],v,p-1);
}
int main(){
int n,m,i,j;
scanf("%d",&n);
for(M=1;M<n+2;M<<=1);
for(i=1;i<=n;i++){
scanf("%d",Tgcd+M+i);
tot++;
root[i]=tot;
insert(root[i-1],root[i],Tgcd[M+i],loga);
}
for(i=M-1;i>0;i--)Tgcd[i]=gcd(Tgcd[i<<1],Tgcd[i<<1|1]);
scanf("%d",&m);
while(m--){
scanf("%d%d",&i,&j);
printf("%d\n",j-i+1-querynum(root[i-1],root[j],querygcd(i,j),loga));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: