[Splay] BZOJ 3729 Gty的游戏

来源:互联网 发布:单片机语言是什么语言 编辑:程序博客网 时间:2024/05/18 20:32

"
题解:
博弈论+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].vusing 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 500005struct 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);elsex->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");elseynum++,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;}


0 0
原创粉丝点击