[BZOJ3729]Gty的游戏(dfs序+splay)
来源:互联网 发布:淘宝上买到假药怎么办 编辑:程序博客网 时间:2024/05/23 01:14
题目描述
传送门
题目大意:给定一棵有根树,每个节点有一些石子,每次可以将不多于L的石子移动到父节点,询问将某个节点的子树中的石子移动到这个节点先手是否有必胜策略。支持几种操作:1 x
询问将x的子树中的石子移动到这个节点先手是否有必胜策略;2 x y
将节点x上的石子修改为y;3 x y z
在节点x上连接一个节点y(x为y的父亲),石子数为z。强制在线。
题解
首先考虑静态的树。对于单个点来说,其实是一个巴什博弈问题,sg函数值就是石子数%(L+1);然后整棵树(子树)是一个阶梯博弈问题,先手必胜当且仅当所有奇数层节点(根为0层)的sg值异或和非0
考虑用splay维护dfs序,对于每一个节点加入一个入栈点一个出栈点,在splay中维护区间奇数层的异或和以及偶数层的异或和,插入一个节点实际上就是在父亲的出栈点之前加入两个点,其余的两个操作就是简单的单点修改和区间查询了
代码
#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;#define N 200005int n,L,m,sz,root,lastans;int tot,point[N],nxt[N],v[N],a[N],h[N],in[N],out[N];int f[N],ch[N][2],key[N],odd[N],even[N];void add(int x,int y){ ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;}void dfs(int x,int fa){ in[x]=++sz;key[sz]=a[x]; h[sz]=h[in[fa]]+1; for (int i=point[x];i;i=nxt[i]) if (v[i]!=fa) dfs(v[i],x); out[x]=++sz;}void update(int x){ if (!x) return; if (h[x]&1) odd[x]=key[x],even[x]=0; else odd[x]=0,even[x]=key[x]; int l=ch[x][0],r=ch[x][1]; if (l) odd[x]^=odd[l],even[x]^=even[l]; if (r) odd[x]^=odd[r],even[x]^=even[r];}int build(int l,int r,int fa){ if (l>r) return 0; int mid=(l+r)>>1; f[mid]=fa; int lch=build(l,mid-1,mid); int rch=build(mid+1,r,mid); ch[mid][0]=lch,ch[mid][1]=rch; update(mid); return mid;}int get(int x){ return ch[f[x]][1]==x;}void rotate(int x){ int old=f[x],oldf=f[old],wh=get(x); ch[old][wh]=ch[x][wh^1]; if (ch[old][wh]) f[ch[old][wh]]=old; ch[x][wh^1]=old; f[old]=x; if (oldf) ch[oldf][ch[oldf][1]==old]=x; f[x]=oldf; update(old); update(x);}void splay(int x,int tar){ for (int fa;(fa=f[x])!=tar;rotate(x)) if (f[fa]!=tar) rotate(get(x)==get(fa)?fa:x); if (!tar) root=x;}int findpre(int x){ splay(x,0); x=ch[root][0]; while (ch[x][1]) x=ch[x][1]; return x;}int findnxt(int x){ splay(x,0); x=ch[root][1]; while (ch[x][0]) x=ch[x][0]; return x;}int main(){ freopen("input.in","r",stdin); freopen("my.out","w",stdout); scanf("%d%d",&n,&L); for (int i=1;i<=n;++i) scanf("%d",&a[i]),a[i]%=(L+1); for (int i=1;i<n;++i) { int x,y;scanf("%d%d",&x,&y); add(x,y),add(y,x); } ++sz;dfs(1,0);++sz; root=build(1,sz,0); scanf("%d",&m); while (m--) { int opt;scanf("%d",&opt); if (opt==1) { int x,ans;scanf("%d",&x); x^=lastans; int aa=findpre(in[x]),bb=findnxt(out[x]); splay(aa,0); splay(bb,aa); if (h[in[x]]&1) ans=even[ch[ch[root][1]][0]]; else ans=odd[ch[ch[root][1]][0]]; if (!ans) puts("GTY"); else puts("MeiZ"),++lastans; } else if (opt==2) { int x,y;scanf("%d%d",&x,&y); x^=lastans,y^=lastans; splay(in[x],0); key[root]=y%(L+1); update(root); } else { int x,y,z;scanf("%d%d%d",&x,&y,&z); x^=lastans,y^=lastans,z^=lastans; int aa=findpre(out[x]),bb=out[x]; splay(aa,0); splay(bb,aa); in[y]=++sz;key[sz]=z%(L+1); h[in[y]]=h[in[x]]+1; f[sz]=ch[root][1];ch[ch[root][1]][0]=sz; out[y]=++sz;key[sz]=0; f[sz]=sz-1;ch[sz-1][1]=sz; update(sz);update(sz-1); update(ch[root][1]);update(root); } }}
0 0
- [BZOJ3729]Gty的游戏(dfs序+splay)
- [博弈 && Splay维护DFS序]BZOJ3729 .Gty的游戏
- [BZOJ3729]Gty的游戏(博弈论+Splay)
- 【bzoj3729】【GTY的游戏】【阶梯博弈+splay】
- 【BZOJ3729】Gty的游戏,博弈+splay
- BZOJ3729: Gty的游戏
- [bzoj3729]Gty的游戏
- [bzoj3729]Gty的游戏
- [bzoj3729]Gty的游戏
- bzoj3729 Gty的游戏
- BZOJ3729: Gty的游戏
- bzoj 3729: Gty的游戏 splay+dfs序+阶梯博弈
- [BZOJ3729]Gty的游戏/[JZOJ4759]石子游戏
- bzoj 3729: Gty的游戏 (博弈+splay)
- [Splay] BZOJ 3729 Gty的游戏
- BZOJ 3729 Gty的游戏
- BZOJ 3729: Gty的游戏
- [BZOJ3786]星系探索(dfs序+splay)
- Java 正则表达式
- iptables ip_conntrack_max 调整
- Java8 lambda表达式10个示例
- lca模板 hdu 2586
- iOS 8 WebKit框架概览
- [BZOJ3729]Gty的游戏(dfs序+splay)
- 懂商业的技术合伙人(9):互联网研究实践指南
- 《浏览器渲染原理及流程》学习笔记
- 复杂链表的复制
- 路由器和交换机的区别
- 2-2 Time类的定义
- 第k个字典序全排列
- WebSocket 是什么原理?为什么可以实现持久连接?
- chapter5——给出年月日,计算该日是该年的第几天