传送门:bzoj2819
题中的Nim游戏其实就是看选中的这几堆石头每堆石头数量的异或和是否为0。
我们只需要维护每个点到根节点路径上的异或和就好了。
每次询问只要把两个节点到根节点路径异或和异或起来(抵消了LCA-ROOT一段)再异或一下LCA就好了。
对于修改,考虑只会影响到该节点为根的子树内的所有节点。直接dfs序建个线段树改一下。
被题面坑了,写了一个手写栈。
#include
using namespace std;
const int M=1e7+10;
const int N=5e5+10;
int n,m,T,f[N][19];
int Q[M],top,a[N],b[N],d[N],ans;
int mv[N<<2],orz[N<<2],bin[20],ori[N];
int head[N],to[N<<1],nxt[N<<1],tot;
int df[N],ot[N],in[N],cnt,as[N];
int opt;
inline int rd(){
char ch;int x=0,f=1;
while(!isdigit(ch=getchar())){if(ch=='-') f=0;}
x=(ch^48);
while(isdigit(ch=getchar())){x=(x<<3)+(x<<1)+(ch^48);}
return f?x:-x;
}
inline void lk(int u,int v)
{to[++tot]=v;nxt[tot]=head[u];head[u]=tot;}
inline int get()
{
char ch=getchar();
while(ch!='Q' && ch!='C') ch=getchar();
return ch=='Q'? 0:1;
}
inline void bfs()
{
int x,ptr;Q[++top]=1;as[1]=a[1];
while(top){
x=Q[top];if(!df[x]) df[x]=++cnt;
for(int i=1;bin[i]<=d[x];i++)
f[x][i]=f[f[x][i-1]][i-1];ptr=1;
for(int &i=ori[x];i;i=nxt[i]){
if(to[i]==f[x][0]) continue;
f[to[i]][0]=x;d[to[i]]=d[x]+1;
as[to[i]]=as[x]^a[to[i]];
if(!in[to[i]]){
Q[++top]=to[i];ptr=0;break;
}
}
if(ptr){in[x]=1;top--;if(!ot[x]) ot[x]=cnt;}
}
}
inline int LCA(int x,int y)
{
if(d[x]int t=d[x]-d[y];
for(int i=0;bin[i]<=t;i++)
if(bin[i]&t) x=f[x][i];
for(int i=18;i>=0;i--){
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
}
if(x==y) return x;
return f[x][0];
}
inline void pushdown(int k)
{
if(orz[k]){
mv[k<<1]^=orz[k];orz[k<<1]^=orz[k];
mv[k<<1|1]^=orz[k];orz[k<<1|1]^=orz[k];
orz[k]=0;
}
}
inline void add(int k,int l,int r,int L,int R,int val)
{
if(l!=r)pushdown(k);
if(l>=L && r<=R){mv[k]^=val;orz[k]=val;return;}
int mid=(l+r)>>1;
if(L<=mid) add(k<<1,l,mid,L,R,val);
if(R>mid) add(k<<1|1,mid+1,r,L,R,val);
}
inline int qr(int k,int l,int r,int pos)
{
if(l==r) return mv[k];
pushdown(k);
int mid=(l+r)>>1;
if(pos<=mid) return qr(k<<1,l,mid,pos);
else return qr(k<<1|1,mid+1,r,pos);
}
inline void cg(int v,int k)
{
int cgd=b[v]^k;b[v]=k;if(!cgd) return;
add(1,1,n,df[v],ot[v],cgd);
}
inline void query(int x,int y)
{
int t=LCA(x,y);
int X=as[x]^qr(1,1,n,df[x]),Y=as[y]^qr(1,1,n,df[y]);
ans=X^Y^b[t];
if(!ans) printf("No\n");
else printf("Yes\n");
}
int main(){
bin[0]=1;for(int i=1;i<20;i++) bin[i]=bin[i-1]<<1;
n=rd();
for(int i=1;i<=n;i++) b[i]=a[i]=rd();
for(int u,v,i=1;ifor(int i=1;i<=n;i++) ori[i]=head[i];
bfs();
T=rd();int cur=0;
while(T--){
opt=get();int U=rd(),V=rd();
if(!opt) query(U,V);
else cg(U,V);
}
return 0;
}