[Splay] BZOJ 3729 Gty的游戏

"
题解:
博弈论+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;
}


你可能感兴趣的:([Splay] BZOJ 3729 Gty的游戏)