树上的Nim取石子游戏。
说白了就是,维护一棵树,支持:修改点权,询问一条路径上点权的xor值是否为零。
可以用树链剖分做。但是介于n和q都50w这么大感觉常数很DT。。
既然它只修改点的话,影响到的只是它这棵子树。那么很容易就想到了dfs序。这个子树就是连续一段。
先维护每个点dfs开始时和结束时的时间戳。修改的时候先在它自己的开始、结束位置上xor它自己变成零,然后再修改。
(x,y)路径上的xor值=query(x的开始) xor query(y的开始) xor lca(x,y)的点权。很好想通。LCA就倍增算一下好了。
没了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define YES *o++='Y',*o++='e',*o++='s',*o++='\n' #define NO *o++='N',*o++='o',*o++='\n' const int maxn=500100,maxm=1000100; int p[maxm],n1[maxm],h[maxn],begin[maxn],end[maxn],bit[maxm],st[maxn],a[maxn],n,ee=0,tot=0; int anc[maxn][20],dep[maxn]; char buf[25000000],*o=buf,*pt=buf; inline int getint(){ int s=0; while(*pt<'0'||*pt>'9')pt++; while(*pt>='0'&&*pt<='9')s=s*10+*pt++-48; return s; }inline char getop(){ while(*pt!='Q'&&*pt!='C') pt++; return *pt++; }inline void ae(int a,int b){ p[ee]=b; n1[ee]=h[a]; h[a]=ee++; p[ee]=a; n1[ee]=h[b]; h[b]=ee++; }inline void dfs(int s){ int top=0; begin[st[++top]=s]=dep[s]=++tot; while(top){ int u=st[top],f=0; for(int i=h[u];~i;i=n1[i]){ if(!~begin[p[i]]){ begin[p[i]]=++tot; anc[p[i]][0]=u; dep[p[i]]=dep[u]+1; st[++top]=p[i]; h[u]=n1[i]; f=1; break; } }if(!f){ end[u]=++tot; top--; } } }inline int lca(int u,int v){ if(dep[u]<dep[v]) swap(u,v); int k=dep[u]-dep[v],j=0; while(k){ if(k&1) u=anc[u][j]; j++,k>>=1; }if(u==v) return u; for(int j=19;~j;j--) if(anc[u][j]!=anc[v][j]) u=anc[u][j],v=anc[v][j]; return anc[u][0]; }inline void modify(int i){ for(int x=begin[i];x<maxm;x+=x&-x) bit[x]^=a[i]; for(int x=end[i];x<maxm;x+=x&-x) bit[x]^=a[i]; }inline int ask(int x){ int r=0; for(;x;x-=x&-x) r^=bit[x]; return r; }int main(){ fread(buf,1,25000000,stdin); n=getint(); for(int i=1;i<=n;i++) a[i]=getint(); memset(h,-1,sizeof(h)); memset(begin,-1,sizeof(begin)); for(int i=1;i<n;i++) ae(getint(),getint()); dfs(1); for(int i=1;i<=n;i++) modify(i); for(int j=1;j<=19;j++) for(int i=1;i<=n;i++) anc[i][j]=anc[anc[i][j-1]][j-1]; int q=getint(),x,y,z; while(q--){ if(getop()=='Q'){ x=getint();y=getint(); if(ask(begin[x])^ask(begin[y])^a[lca(x,y)]) YES; else NO; }else{ x=getint();y=getint(); modify(x); a[x]=y; modify(x); } }return fwrite(buf,1,o-buf,stdout),0; }