分块大法好
代码
//By AcerMo
#include<set>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 1e5+7;
int a[maxn],n,m;
int l[1000],r[1000];
int block,cnt,bloc[maxn];
int Gcd[maxn],Xor[maxn];
set<int>S[990];
inline int gcd(int a,int b)
{
if(!b)return a;
return gcd(b,a%b);
}
inline int read()
{
int x=0;char ch=getchar();
while (ch>'9'||ch<'0') ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
inline void build(int x)
{
S[x].clear();
Gcd[l[x]]=a[l[x]],Xor[l[x]]=a[l[x]];
S[x].insert(Xor[l[x]]);
for(int i=l[x]+1;i<=r[x];i++)
{
Gcd[i]=gcd(Gcd[i-1],a[i]),Xor[i]=Xor[i-1]^a[i];
S[x].insert(Xor[i]);
}
return ;
}
int main()
{
n=read();block=sqrt(n);
for(int i=1;i<=n;i++) a[i]=read();
if(n%block) cnt=n/block+1;
else cnt=n/block;
for(int i=1;i<=cnt;i++)
l[i]=(i-1)*block+1,r[i]=i*block;
r[cnt]=n;
for(int i=1;i<=n;i++)
bloc[i]=(i-1)/block+1;
for(int i=1;i<=cnt;i++) build(i);
m=read();
for (int i=1;i<=m;i++)
{
char s[10];
scanf("%s",s);
if(s[0]=='M')
{
int x,y;
scanf("%d%d",&x,&y);x++;
a[x]=y;build(bloc[x]);
}
else
{
long long int x;scanf("%lld",&x);
int flag=0,lg=0,lx=0;
for(int i=1;i<=cnt;i++)
{
int T=gcd(lg,Gcd[r[i]]);
if(T!=lg)
{
for(int j=l[i];j<=r[i];j++)
if((long long)(Xor[j]^lx)*(long long)(gcd(lg,Gcd[j]))==x)
{flag=j;break;}
if(flag>0)break;
}
else
{
if(x%T==0&&S[i].count((int)(x/T)^lx))
{
for(int j=l[i];j<=r[i];j++)
if((long long)(Xor[j]^lx)*(long long)(gcd(lg,Gcd[j]))==x)
{flag=j;break;}
if(flag>0)break;
}
}
lg=T,lx^=Xor[r[i]];
}
if(flag>0) printf("%d\n",flag-1);
else puts("no");
}
}
return 0;
}