BZOJ2819 Nim
2017-12-13 18:43
267 查看
题目大意
给定一棵树,有两种操作。1 u v 询问若在v到u间的路径上的石子堆中玩Nim游戏,先手是否有必胜策略。
2 v k 将v节点上的石子个数改为k
请输出所有询问的答案(Yes/No)
Sample Input
51 3 5 2 5
1 5
3 5
2 5
1 4
6
Q 1 2
Q 3 5
C 3 7
Q 1 2
Q 2 4
Q 5 3
Sample Output
YesNo
Yes
Yes
Yes
Solution
Nim游戏中先手必胜的条件是所有数的异或和>0,所以只要维护u,v这条链上所有数的异或和即可。可以用树剖做,但是有复杂度更优的算法。将每个点的入栈时间in[u]和出栈时间out[u]记下,u入栈时的节点上记val[u],u出栈时的节点上记val[u],这样入栈和出栈的时候能够相互抵消。对于一组询问u,v,发现这条链上(除LCA)的点刚好入一次栈,而不在这条链上的点则要么不入栈,要么入栈后又出栈,所以in[u]到in[v]的异或和就是u,v链(除LCA)上的异或和,可以用树状数组维护。代码
#include<cstdio> #include<algorithm> #define lowbit(x) x&(-x) using namespace std; int fa[500010][20],next[1000010],vet[1000010],head[500010],deep[500010]; int tree[1000010],num,n,ti,in[500010],out[500010],a[500010]; char st[10]; void add(int u,int v) { next[++num]=head[u]; head[u]=num; vet[num]=v; } int query(int x) { int ans=0; for (;x;x-=lowbit(x)) ans^=tree[x]; return ans; } void modify(int x,int key) { for (;x<=ti;x+=lowbit(x)) tree[x]^=key; } void dfs(int u) { in[u]=++ti; for (int i=head[u];i;i=next[i]) { int v=vet[i]; if (!in[v]) fa[v][0]=u,deep[v]=deep[u]+1,dfs(v); } out[u]=++ti; } int lca(int x,int y) { if (deep[x]<deep[y]) swap(x,y); // printf("%d %d\n",x,y); for (int i=19;i>=0;i--) if (fa[x][i]&&deep[fa[x][i]]>=deep[y]) x=fa[x][i]; if (x==y) return x; for (int i=19;i>=0;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0]; } int main() { int m; scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&a[i]); for (int i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); add(u,v); add(v,u); } ti=0; deep[1]=1; dfs(1); for (int i=1;i<=19;i++) for (int j=1;j<=n;j++) fa[j][i]=fa[fa[j][i-1]][i-1]; for (int i=1;i<=n;i++) modify(in[i],a[i]),modify(out[i],a[i]); int u,v; //lca(5,3); scanf("%d",&m); while (m--) { scanf("%s",st); if (st[0]=='Q') { scanf("%d%d",&u,&v); int ans=query(in[u])^query(in[v])^a[lca(u,v)]; if (ans) puts("Yes"); else puts("No"); } else { scanf("%d%d",&u,&v); modify(in[u],a[u]),modify(out[u],a[u]); a[u]=v; modify(in[u],v),modify(out[u],v); } } return 0; }
相关文章推荐
- 【BZOJ 2819】 Nim
- BZOJ 2819 Nim 树链剖分
- BZOJ 2819 Nim
- Bzoj2819:Nim:树链剖分
- 【(博弈)dfs序+树状数组】BZOJ2819-Nim
- [bzoj2819]Nim
- bzoj2819 Nim
- BZOJ 2819 Nim 树链剖分
- 【BZOJ2819】Nim 博弈论+树链剖分
- [BZOJ 2819]nim(DFS序+树状数组+SG博弈)
- BZOJ_2819_Nim_树状数组维护出栈入栈序
- Bzoj2819 Nim
- BZOJ 2819: Nim dfs序维护树状数组,倍增
- BZOJ 2819: Nim 树状数组+lca+dfs序
- [bzoj2819][树链剖分][博弈]Nim
- 【BZOJ2819】Nim 树状数组+LCA
- [BZOJ2819]Nim-树状数组-dfs序
- bzoj2819 NIM 树上两点间抑或值
- [BZOJ2819] Nim && dfs序 + 树状数组 + LCA
- bzoj2819 Nim