题目链接:Nim
线段树维护异或值的沙茶题
然而dfs会爆栈所以得开手工栈(见代码)
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=500010;
int tot=0,h[maxn],ind=0,s[maxn],fa[maxn];
struct edge{int to,next;}G[maxn<<1];
int dep[maxn],Belong[maxn],pos[maxn];
int v[maxn],ans=0,n,m,fz[maxn];
struct seg{
int l,r,v;
seg *lc,*rc;
};
seg *root=new seg();
char str[5];
void add(int x,int y){
G[++tot].to=y;G[tot].next=h[x];h[x]=tot;
}
void dfs1(int x){
s[x]=1; dep[x]=dep[fa[x]]+1;
for (int i=h[x];i;i=G[i].next){
int v=G[i].to;
if (v==fa[x]) continue;
fa[v]=x; dfs1(v); s[x]+=s[v];
}
}
void dfs2(int x,int L){
pos[x]=++ind; int k=0; Belong[x]=L; fz[ind]=x;
for (int i=h[x];i;i=G[i].next)
if (s[G[i].to]>s[k]&&dep[G[i].to]>dep[x]) k=G[i].to;
if (!k) return; dfs2(k,L);
for (int i=h[x];i;i=G[i].next)
if (dep[G[i].to]>dep[x]&&k!=G[i].to) dfs2(G[i].to,G[i].to);
}
void push_up(seg *p){
p->v=p->lc->v^p->rc->v;
}
void build(seg *p,int l,int r){
p->l=l; p->r=r;
if (l+1==r){
p->v=v[fz[l]]; p->lc=p->rc=NULL; return;
}else if (l+1<r){
int mid=(l+r)>>1;
p->lc=new seg();
p->rc=new seg();
if (l<mid) build(p->lc,l,mid);
if (mid<r) build(p->rc,mid,r);
push_up(p);
}
}
void update(seg *p,int l,int r,int val){
if (l<=p->l&&p->r<=r){p->v=val;return;}
int mid=(p->l+p->r)>>1;
if (l<mid) update(p->lc,l,r,val);
if (mid<r) update(p->rc,l,r,val);
push_up(p);
}
void ask(seg *p,int l,int r){
if (l<=p->l&&p->r<=r){ans^=p->v;return;}
int mid=(p->l+p->r)>>1;
if (l<mid) ask(p->lc,l,r);
if (mid<r) ask(p->rc,l,r);
}
int query(int x,int y){
int sum=0;
while (Belong[x]!=Belong[y]){
if (dep[Belong[x]]<dep[Belong[y]]) swap(x,y);
ans=0; ask(root,pos[Belong[x]],pos[x]+1);
sum^=ans; x=fa[Belong[x]];
}
if (dep[x]<dep[y]) swap(x,y);
ans=0; ask(root,pos[y],pos[x]+1);
sum^=ans;
return sum;
}
int main(){
int __size__=30<<20;
char *__p__=(char*)malloc(__size__)+__size__;
__asm__("movl %0, %%esp\n"::"r"(__p__));
scanf("%d",&n);
for (int i=1;i<=n;++i)scanf("%d",&v[i]);
for (int i=1;i<n;++i){
int x,y;
scanf("%d%d",&x,&y);
add(x,y); add(y,x);
}
dfs1(1);
dfs2(1,1);
build(root,1,n+1);
scanf("%d",&m);
for (int i=1;i<=m;++i){
scanf("%s",str+1);
if (str[1]=='C'){
int x,y; scanf("%d%d",&x,&y);
update(root,pos[x],pos[x]+1,y);
}else if (str[1]=='Q'){
int x,y; scanf("%d%d",&x,&y);
int ret=query(x,y);
if (ret) printf("Yes\n");
else printf("No\n");
}
}
}