"
题解:
博弈论+Splay维护dfs序
想会做这道题首先要知道两个Nim游戏的经典变形。
第一个是加入一次只能选m个的限制。
第二个是“阶梯博弈”(POJ 1704),就是有一个楼梯,每次可以把一阶的任意个棋子移到下面一个台阶,不能移动(0号台阶不能向下移动)的玩家输。
第一个问题的解决方法是把所有的数 mod (m+1),因为显然加入这个限制之后每个子游戏的sg函数值变成了sg(n) = n%(m+1)。
第二个问题可以转换成Nim游戏,方法是如果对方移动了偶数层的棋子,那么你下一步可以把他刚移动的棋子再向下移动。这样偶数层上的棋子就可以视为不存在了,如果把一个奇数层的棋子移动到下一层,那么我们把它看成消失了,这样就变成了Nim游戏,也就是说只用考虑奇数层的棋子sg函数的异或值就行了。
在树上也同理,对于任意一棵子树,如果把根深度定义为0,那么也只要考虑深度为奇数的异或和。
题目就变成了支持动态修改,加点,维护子树信息,随便用个什么数据结构维护一下dfs序就行了。
"
传送门:http://timeplayer.blog.163.com/blog/static/2037182542014102063732763/
Orzzz
#include<cstdio> #include<cstdlib> #include<map> #include<algorithm> #define V G[p].v using namespace std; inline char nc() { static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x) { char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } struct Splay{ #define oo 1<<30 #define ND_MAX 500005 struct node{ int a[2],d,val; int size; node *p,*ch[2]; bool dir() { return p->ch[1]==this; } void setc(node *x,int d) { ch[d]=x; x->p=this; } void update(){ size=ch[0]->size+ch[1]->size+1; a[0]=(ch[0]->a[0])^(ch[1]->a[0]); a[1]=(ch[0]->a[1])^(ch[1]->a[1]); a[d]^=val; } }*root,*null; node Mem[ND_MAX],*Stack[ND_MAX]; int top; inline void init_Memory(){ for (int i=0;i<ND_MAX;i++) Stack[i]=Mem+i; top=ND_MAX-1; } inline node* New_Node(){ node *p=Stack[top--]; p->p=p->ch[0]=p->ch[1]=null; p->size=1; return p; } inline void Del_Node(node *p){ Stack[++top]=p; } Splay() { init_Memory(); root=null=New_Node(); null->p=null->ch[1]=null->ch[0]=null; null->size=0; } inline void rot(node *x){ if (x==null) return; if (x->p==root) root=x; bool d=x->dir(); node *p=x->p; if (p->p!=null) p->p->setc(x,p->dir()); else x->p=null; p->setc(x->ch[d^1],d); x->setc(p,d^1); x->update(); p->update(); } inline void splay(node *&rt,node *x){ if (x==null) return; while (x!=rt) if (x->p==rt) rot(x); else x->dir()==x->p->dir()?(rot(x->p),rot(x)):(rot(x),rot(x)); rt=x; x->update(); } inline void insert(node *z){ node *x=root,*y=null; if (root==null) { root=z; return; } while (x!=null) y=x,x=x->ch[1]; y->setc(z,1); splay(root,z); } inline node* findkth(node *&rt,int k){ if (k>rt->size) return null; node *x=rt; while (k){ if (k==x->ch[0]->size+1) break; k>x->ch[0]->size+1?k-=x->ch[0]->size+1,x=x->ch[1]:x=x->ch[0]; } splay(root,x); return x; } inline node *nxt(node *x){ node *p=x->ch[1]; while (p->ch[0]!=null) p=p->ch[0]; return p; } inline void print(node *x){ if (x==null) return; printf("%d",x->val); putchar('('); print(x->ch[0]); putchar(')'); putchar('('); print(x->ch[1]); putchar(')'); } }splay; struct edge{ int u,v,next; }; int head[200005],inum; edge G[400005]; inline void add(int u,int v,int p) { G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p; } map<int,int>id; int n,L,ynum; int w[200005],d[200005]; Splay::node *pos[400005],*last[400005]; inline void dfs(int u,int fa) { d[u]=d[fa]^1; Splay::node *p=splay.New_Node(); p->d=d[u]; p->val=w[u]; splay.insert(p); pos[u]=p; for (int p=head[u];p;p=G[p].next) if (V!=fa) dfs(V,u); p=splay.New_Node(); splay.insert(p); last[u]=p; } int main() { int _u,_v,_x,Q,order,Xor; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); read(L); for (int i=1;i<=n;i++) read(w[i]),w[i]%=(L+1),id[i]=i; for (int i=1;i<n;i++) read(_u),read(_v),add(_u,_v,++inum),add(_v,_u,++inum); dfs(1,0); for (int i=1;i<=10;i++) splay.splay(splay.root,pos[rand()%n+1]); // splay.print(splay.root); printf("\n"); read(Q); while (Q--) { read(order); if (order==1){ read(_u); _u^=ynum; _u=id[_u]; splay.splay(splay.root,pos[_u]); // splay.print(splay.root);printf("\n"); splay.splay(splay.root->ch[1],last[_u]); // splay.print(splay.root);printf("\n"); Xor=splay.root->ch[1]->ch[0]->a[d[_u]^1]; if (Xor==0) printf("GTY\n"); else ynum++, printf("MeiZ\n"); } else if (order==2){ read(_u); read(_v); _u^=ynum; (_v^=ynum)%=(L+1); _u=id[_u]; splay.splay(splay.root,pos[_u]); // splay.print(splay.root);printf("\n"); splay.root->val=_v; splay.root->update(); } else if (order==3){ read(_u); read(_v); read(_x); _u^=ynum; _v^=ynum; _x^=ynum; _x%=(L+1); id[_v]=++n; _u=id[_u]; d[n]=d[_u]^1; pos[n]=splay.New_Node(); pos[n]->d=d[_u]^1; pos[n]->val=_x; last[n]=splay.New_Node(); splay.splay(splay.root,pos[_u]); // splay.print(splay.root);printf("\n"); Splay::node *t=splay.nxt(pos[_u]); splay.splay(splay.root->ch[1],t); // splay.print(splay.root);printf("\n"); splay.root->ch[1]->setc(pos[n],0); splay.root->ch[1]->ch[0]->setc(last[n],1); splay.root->ch[1]->ch[0]->update(); splay.root->ch[1]->update(); splay.root->update(); // splay.print(splay.root);printf("\n"); } } return 0; }