我们知道Nim游戏是否先手必胜只需看异或和是否为0即可。
因此此题我们就是要维护路径异或和和单调修改。
可以dfs序+树状数组来做,维护每个点到根的异或和。
#include
#include
#include
#include
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 500010
inline char gc(){
static char buf[1<<16],*S,*T;
if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
char op[5];
inline void get_S(){
op[1]=gc();while(op[1]!='Q'&&op[1]!='C') op[1]=gc();
}
int n,m,h[N],num=0,in[N],out[N],dfn=0,a[N],dep[N];
int tot=0,mn[N<<1][20],Log[N<<1],pos[N],c[N];
struct edge{
int to,next;
}data[N<<1];
inline void dfs(int x,int Fa){
in[x]=++dfn;mn[++tot][0]=x;pos[x]=tot;
for(int i=h[x];i;i=data[i].next){
int y=data[i].to;if(y==Fa) continue;
dep[y]=dep[x]+1;dfs(y,x);mn[++tot][0]=x;
}out[x]=dfn;
}
inline void add(int x,int val){
for(;x<=n;x+=x&-x) c[x]^=val;
}
inline int ask(int x){
int res=0;for(;x;x-=x&-x) res^=c[x];return res;
}
inline int Min(int x,int y){
return dep[x]<=dep[y]?x:y;;
}
inline void initrmq(){
Log[0]=-1;
for(int i=1;i<=n*2;++i) Log[i]=Log[i>>1]+1;
for(int i=1;i<=Log[n<<1];++i)
for(int j=1;j<=n*2;++j){
if(j+(1<1)>2*n-1) break;
mn[j][i]=Min(mn[j][i-1],mn[j+(1<1)][i-1]);
}
}
inline int lca(int x,int y){
x=pos[x];y=pos[y];if(x>y) swap(x,y);
int d=Log[y-x+1];
return Min(mn[x][d],mn[y-(1<1][d]);
}
int main(){
// freopen("a.in","r",stdin);
n=read();for(int i=1;i<=n;++i) a[i]=read();
for(int i=1;iint x=read(),y=read();
data[++num].to=y;data[num].next=h[x];h[x]=num;
data[++num].to=x;data[num].next=h[y];h[y]=num;
}dfs(1,0);initrmq();
for(int i=1;i<=n;++i) add(in[i],a[i]),add(out[i]+1,a[i]);
m=read();
while(m--){
get_S();int x=read(),y=read();
if(op[1]=='Q'){
int res=ask(in[x])^ask(in[y])^a[lca(x,y)];
puts(res?"Yes":"No");continue;
}int res=a[x]^y;add(in[x],res);add(out[x]+1,res);a[x]=y;
}return 0;
}