分块维护 块内gcd 以及 块内出现的每个异或前缀和及位置,修改可以暴力重构整个块,查询则利用gcd的性质,由于前缀gcd的取值种数是对数级的,对前缀gcd不变的块二分查询,前缀gcd改变的块暴力计算,总复杂度约为O(nsqrt(n)log(max(a_i)))
#include<cstdio>
#include<cmath>
#include<algorithm>
char buf[5000007],*ptr=buf-1;
template<class T>
void _(T&x){
int c=*++ptr;
x=0;
while(c<48)c=*++ptr;
while(c>47)x=x*10+c-48,c=*++ptr;
}
int _c(){
int c=*++ptr;
while(c>‘Z‘||c<‘A‘)c=*++ptr;
int r=c;
while(c>=‘A‘&&c<=‘Z‘)c=*++ptr;
return r;
}
bool dt[555];
int n,q,a[100007],B,id[100007],ls[555],rs[555],gs[555];
int xa[555];
struct pos{
int x,y;
bool operator<(pos w)const{return y!=w.y?y<w.y:x<w.x;}
}vs[100007];
int gcd(int a,int b){
for(int c;b;c=a,a=b,b=c%b);
return a;
}
int bit[100007];
void xadd(int w,int a){
for(;w<=n;w+=w&-w)bit[w]^=a;
}
int xsum(int w){
int s=0;
for(;w;w-=w&-w)s^=bit[w];
return s;
}
int main(){
fread(buf,1,sizeof(buf),stdin);
_(n);
B=sqrt(n);
for(int i=1;i<=n;++i)_(a[i]),id[i]=(i-1)/B,xadd(i,a[i]);
for(int i=0;i<=id[n];++i)ls[i]=i*B+1,rs[i]=ls[i]+B-1,dt[i]=1;
rs[id[n]]=n;
for(_(q);q;--q){
if(_c()==‘M‘){
int x,y,z;
_(x);_(y);
++x;
z=a[x]^y;
xadd(x,z);
a[x]=y;
int b=id[x];
dt[b]=1;
for(int i=b+1;i<=id[n];++i)xa[i]^=z;
}else{
long long x;
_(x);
for(int i=0,gl=0;i<=id[n];++i){
if(dt[i]){
dt[i]=xa[i]=gs[i]=0;
int sl=xsum(ls[i]-1);
for(int j=ls[i];j<=rs[i];++j){
gs[i]=gcd(gs[i],a[j]);
sl^=a[j];
vs[j]=(pos){j,sl};
}
std::sort(vs+ls[i],vs+rs[i]+1);
}
int g=gcd(gl,gs[i]);
if(gl!=g){
int sl=xsum(ls[i]-1);
for(int j=ls[i];j<=rs[i];++j){
gl=gcd(gl,a[j]);
sl^=a[j];
if(1ll*gl*sl==x){
printf("%d\n",j-1);
goto o;
}
}
}else if(x%gl==0&&x/gl<1073741824){
int z=x/gl^xa[i];
pos*it=std::lower_bound(vs+ls[i],vs+rs[i]+1,(pos){0,z});
if(it!=vs+rs[i]+1&&it->y==z){
printf("%d\n",it->x-1);
goto o;
}
}
}
puts("no");
o:;
}
}
return 0;
}