bzoj2819: Nim(博弈+树剖)
2819: Nim
题目:传送门
题解:
很久之前学博弈的时候看过的一道水题,其实算不上博弈吧...
直接套上一个裸的树剖啊,把路径上的点值全都xor(xor满足结合率所以就不管那么多随便搞啦)
dog B 肉老师,竟然不告诉我它卡常,搞得我TLE几百年
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 #include<iostream> 7 using namespace std; 8 inline int read() 9 { 10 int f=1,x=0;char ch; 11 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 12 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 13 return f*x; 14 } 15 struct node 16 { 17 int x,y,next; 18 }a[1110000];int len,last[510000]; 19 inline void ins(int x,int y) 20 { 21 len++;a[len].x=x;a[len].y=y; 22 a[len].next=last[x];last[x]=len; 23 } 24 struct trnode 25 { 26 int l,r,c,lc,rc; 27 }tr[1110000];int trlen; 28 inline void bt(int l,int r) 29 { 30 int now=++trlen; 31 tr[now].l=l;tr[now].r=r;tr[now].c=0; 32 tr[now].lc=tr[now].rc=-1; 33 if(l<r) 34 { 35 int mid=(tr[now].l+tr[now].r)/2; 36 tr[now].lc=trlen+1;bt(l,mid); 37 tr[now].rc=trlen+1;bt(mid+1,r); 38 } 39 } 40 inline void change(int now,int p,int c) 41 { 42 if(tr[now].l==tr[now].r){tr[now].c=c;return ;} 43 int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2; 44 if(p<=mid)change(lc,p,c); 45 else change(rc,p,c); 46 tr[now].c=tr[lc].c^tr[rc].c; 47 } 48 inline int getsum(int now,int l,int r) 49 { 50 if(tr[now].l==l && r==tr[now].r)return tr[now].c; 51 int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2; 52 if(r<=mid)return getsum(lc,l,r); 53 else if(mid+1<=l)return getsum(rc,l,r); 54 return getsum(lc,l,mid)^getsum(rc,mid+1,r); 55 } 56 int n,fa[510000],son[510000],dep[510000],tot[510000]; 57 inline void pre_tree_node(int x) 58 { 59 son[x]=0;tot[x]=1; 60 for(register int k=last[x];k;k=a[k].next) 61 { 62 int y=a[k].y; 63 if(y!=fa[x]) 64 { 65 dep[y]=dep[x]+1; 66 fa[y]=x; 67 pre_tree_node(y); 68 if(tot[y]>tot[son[x]])son[x]=y; 69 tot[x]+=tot[y]; 70 } 71 } 72 } 73 int top[510000],ys[510000],id,tp; 74 inline void pre_tree_edge(int x) 75 { 76 int tt=tp;top[x]=tp;ys[x]=++id; 77 if(son[x]!=0)pre_tree_edge(son[x]); 78 for(register int k=last[x];k;k=a[k].next) 79 { 80 int y=a[k].y; 81 if(y!=son[x] && y!=fa[x]) 82 { 83 tp=y; 84 pre_tree_edge(y); 85 tp=tt; 86 } 87 } 88 } 89 int sol(int x,int y) 90 { 91 int ans=0,tx=top[x],ty=top[y]; 92 while(tx!=ty) 93 { 94 if(dep[tx]>dep[ty])swap(tx,ty),swap(x,y); 95 ans^=getsum(1,ys[ty],ys[y]); 96 y=fa[ty];ty=top[y]; 97 } 98 if(x==y)return ans^getsum(1,ys[x],ys[x]); 99 else 100 { 101 if(dep[x]>dep[y])swap(x,y); 102 return ans^getsum(1,ys[x],ys[y]); 103 } 104 } 105 int st[510000],Q; 106 char s[3]; 107 int main() 108 { 109 //freopen("a.in","r",stdin);freopen("a.out","w",stdout); 110 n=read();for(int i=1;i<=n;++i)st[i]=read(); 111 len=0;memset(last,0,sizeof(last)); 112 for(register int i=1;i<n;++i) 113 { 114 int x=read(),y=read(); 115 ins(x,y);ins(y,x); 116 } 117 fa[1]=0;dep[1]=0;pre_tree_node(1); 118 id=0;tp=1;pre_tree_edge(1); 119 trlen=0;bt(1,id); 120 for(register int i=1;i<=n;++i)change(1,ys[i],st[i]); 121 Q=read(); 122 while(Q--) 123 { 124 scanf("%s",s+1);int x=read(),y=read(); 125 if(s[1]=='Q') 126 { 127 if(sol(x,y)!=0)printf("Yes\n"); 128 else printf("No\n"); 129 } 130 else change(1,ys[x],y); 131 } 132 return 0; 133 }