"The main topic"
Ordinary Nim game for: Two people to play, n heap of stones, each turn can take one of the piles of any number, can be taken, but can not be taken. Who can not take who loses. There is a winning strategy for this game. Now for each heap number 1,2,3,4,... N, the link between the heap and the heap, no self-loops and heavy edges, from any heap to any heap only a single path can be reached. Then he kept doing the following:
1. Randomly select two heap v,u, ask if you play NIM game in the gravel heap on the path between V and U, if there is a winning strategy, if there is, vfleaking will consider these gravel heap as one of the initial situations to pit the players.
2. Change the number of stones in Heap V to K.
Ideas
For ordinary Nim games, if all the stones are different in number or 1, then win, otherwise not.
Now these heaps make up a tree, and we use Query (x) to denote an XOR value from X to the root node, an XOR and stomach query (u) XOR query (v) XOR (Num[lca (U,V)) on the path of the U-V, apparently, because their recent public ancestors were repeated xor two times, Cancel out, so it's different or back. )
The first approach is to use the quantitative subdivision to map to the segment tree to solve.
Because the value of each U changes, it only affects the query value of it and its subtree, and the DFS sequence of a node and its subtree is continuous and can be maintained with a tree array.
A topic with the same nature as the DFS sequence is more difficult to combine with AC automata →♦
The tree array maintains XOR and maintenance, and is equivalent to a tree-like array of interval-modified point queries. Notice how to modify the operation: Delta=num[u]^v, so that the original num[u] is offset, leaving a v. This is easier, but don't forget to num[u]→v the changes.
1#include <iostream>2#include <cstdio>3#include <cstring>4#include <algorithm>5#include <vector>6 using namespacestd;7 Const intmaxn=500000+ -;8 Const intdeg= -;9vector<int>E[MAXN];Ten intSTART[MAXN],END[MAXN]; One intN,NUM[MAXN],E[MAXN]; A intANC[MAXN][DEG],DEP[MAXN]; - intCnt=0; - the voidAddedge (intUintv) - { - E[u].push_back (v); - e[v].push_back (u); + } - + /*Tree array interval modification point query part*/ A intLowbit (intx) at { - return(x& (-x)); - } - - voidModifyintXintYintDelta) - { in if(x<y) Swap (x, y); -X + +; to while(X<MAXN) e[x]^=delta,x+=lowbit (x); + while(Y<MAXN) e[y]^=delta,y+=lowbit (y); - } the * intQueryintx) $ {Panax Notoginseng intret=0; - while(x) ret^=e[x],x-=lowbit (x); the returnret; + } A the /*initialization of DFS sequence parts and LCA*/ + voidDfsintUintFaintd) - { $dep[u]=D; $anc[u][0]=FA; -start[u]=++CNT; - for(intI=0; I<e[u].size (); i++) the if(E[U][I]!=FA) DFS (e[u][i],u,d+1); -end[u]=CNT;Wuyi } the - /*LCA Section*/ Wu voidGetanc () - { About for(intI=1; i<deg;i++) $ for(intj=1; j<=n;j++) -anc[j][i]=anc[anc[j][i-1]][i-1]; - } - A intSwimintUintH) + { the intI=0; - while(H) $ { the if(h&1) u=Anc[u][i]; thei++; theh>>=1; the } - returnu; in } the the intLcaintUintv) About { the if(dep[u]<Dep[v]) swap (U,V); theU=swim (u,dep[u]-dep[v]); the if(U==V)returnu; + for(inti=deg-1; i>=0; i--) - { the if(anc[u][i]!=Anc[v][i])Bayi { theu=Anc[u][i]; thev=Anc[v][i]; - } - } the returnanc[u][0]; the } the the /*Main*/ - voidInit () the { thescanf"%d",&n); the for(intI=1; i<=n;i++) scanf ("%d",&num[i]);94 for(intI=0; i<n-1; i++) the { the intu,v; thescanf"%d%d",&u,&v);98 Addedge (u,v); About } -Dfs1,0,0);101 Getanc ();102Memset (E,0,sizeof(e));103 for(intI=1; i<=n;i++) Modify (Start[i],end[i],num[i]);104 } the 106 voidSolve ()107 {108 intQ;109scanf"%d",&q); the for(intI=0; i<q;i++)111 { the Charc[2];intu,v;113scanf"%s%d%d",c,&u,&v); the if(c[0]=='Q') the { the intLca=LCA (U,V);117 intAns=query (Start[u]) ^query (Start[v]) ^Num[lca];118 if(ANS) puts ("Yes");ElsePuts"No");119 } - Else 121 {122Modify (start[u],end[u],num[u]^v);123num[u]=v;124 } the }126 }127 - intMain ()129 { the init ();131 solve (); the return 0;133}
"(game) DFS sequence + tree array" Bzoj2819-nim