您的位置:首页 > 其它

[Splay] BZOJ 3729 Gty的游戏

2016-03-13 14:09 375 查看
"

题解:

博弈论+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
=d[_u]^1;
pos
=splay.New_Node();
pos
->d=d[_u]^1; pos
->val=_x;
last
=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
,0);
splay.root->ch[1]->ch[0]->setc(last
,1);
splay.root->ch[1]->ch[0]->update();
splay.root->ch[1]->update();
splay.root->update();
//			splay.print(splay.root);printf("\n");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: