Description

给定一棵n个节点的数,第i个节点上有ai个石子。
有两个人在van游戏,每次操作者可以从x的子树中的任意一个点选择不超过m个石子移动到它的父亲。
给定t次操作,每次操作询问为x的子树中做游戏先手是否必胜,或者修改一个点的石子数量,又或者是给x新增一个儿子y,石子个数为z。
n,t<=50000,保证任何时刻树中结点个数和编号不超过50000

Solution

如果你看到了这里,先别急着往下看。
因为出题人有毒!!!
说好的结点个数不超过50000呢?

好了,现在我们来讲讲正解。
首先你得会经典NIM游戏。
我们先来分析一下sg函数值。
sg[x]=mexmin(x,m)i=1(sg[x−i])且sg[0]=0 sg[x]=mex_{i=1}^{min(x,m)}(sg[x-i])且sg[0]=0
归纳可得 sg[x]=xmod(m+1) sg[x]=x\mod (m+1)
然后,我们可以发现这是个阶梯NIM游戏。
简单点讲,我们只需要关注奇数层的异或和。(根节点的深度为0)
为什么呢?因为你移动偶数层,别人就可以立马把它移到奇数层。
所以移动偶数层等于没动。

然后就是要处理子树问题了。
动态加点可以用LCT,但子树处理似乎要用Euler Tour Tree…..
本蒟蒻不会写。。。
那么我们发现每次加入的点都是新的(似乎直接插入一棵子树也不是问题)
那么我们可以用splay来维护dfs序。
由于序列是动态的,所以我们需要动态维护每个点的size。
不过简单点想,一个节点所掌管的区间就是这个节点为左端点,节点右边第一个深度小于等于它自己的那个点为右端点。
于是我们可以维护区间min_dep值。
然后维护深度为奇数和偶数的层数的异或和。(奇数和总和我不拦着你)
注意这道题要在右边插入一个虚拟节点,但不用在左边插。
还有,插入没必要搞得那么麻烦,只插入一个点的话,直接插就好啦。

从a_crazy_czy那里学来的姿势,这道题可以用定期重构来做。
似乎还可以用树分块(Gty系列)。

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define rep(i,a) for(int i=last[a];i;i=next[i])
#define N 100005
#define Null N-1
using namespace std;
const int inf=0x7fffffff;
int t[N][2],f[N],size[N],sg[N],sg_0[N],sg_1[N],dep[N];
int d[N],n,m,q,x,y,z,l,tot,cnt,ans,bz,root;
int last[N],to[N*2],next[N*2];
void add(int x,int y) {to[++l]=y;next[l]=last[x];last[x]=l;
}
void updata(int x) {int l=t[x][0],r=t[x][1];dep[x]=min(d[x],min(dep[l],dep[r]));size[x]=size[l]+size[r]+1;sg_0[x]=sg_0[l]^sg_0[r];sg_1[x]=sg_1[l]^sg_1[r];if (d[x]&1) sg_1[x]^=sg[x];else sg_0[x]^=sg[x];
}
int son(int x) {return t[f[x]][1]==x;}
void rotate(int x) {int y=f[x],z=son(x);f[x]=f[y];if (f[x]) t[f[x]][son(y)]=x;if (t[x][1-z]) f[t[x][1-z]]=y;f[y]=x;t[y][z]=t[x][1-z];t[x][1-z]=y;updata(y);updata(x);
}
void splay(int x,int y) {while (f[x]!=y) {if (f[f[x]]!=y) if (son(x)==son(f[x])) rotate(f[x]);else rotate(x);rotate(x);}if (!y) root=x;
}
void dfs(int x,int y) {if (y) d[x]=d[y]+1;if (root) f[x]=root,t[root][1]=x;splay(x,0);rep(i,x) if (to[i]!=y) dfs(to[i],x);
}
int get(int x,int y) {if (dep[t[x][0]]<=y) return get(t[x][0],y);else if (d[x]<=y) return x;else return get(t[x][1],y);
}
int main() {scanf("%d%d",&n,&m);d[0]=dep[0]=inf;fo(i,1,n) scanf("%d",&sg[i]),sg[i]%=(m+1);fo(i,1,n-1) scanf("%d%d",&x,&y),add(x,y),add(y,x);d[1]=1;dfs(1,0);f[Null]=root;t[root][1]=Null;splay(Null,0);for(scanf("%d",&q);q;q--) {scanf("%d",&bz);if (bz==1) {scanf("%d",&x);x^=cnt;splay(x,0);int y=get(t[x][1],d[x]);splay(y,x);if (d[x]&1) ans=sg_0[t[y][0]];else ans=sg_1[t[y][0]];if (ans) printf("MeiZ\n"),cnt++;else printf("GTY\n");} else if (bz==2) {scanf("%d%d",&x,&y);x^=cnt;y^=cnt;splay(x,0);sg[x]=y%(m+1);updata(x);} else {scanf("%d%d%d",&x,&y,&z);x^=cnt;y^=cnt;z^=cnt;d[y]=d[x]+1;sg[y]=z%(m+1);splay(x,0);f[t[x][1]]=y;f[y]=x;t[y][1]=t[x][1];t[x][1]=y;updata(t[y][1]);updata(y);updata(x);}}
}

[bzoj3729]Gty的游戏相关推荐

  1. BZOJ3729: Gty的游戏(伪ETT)

    题面 传送门 前置芝士 巴什博奕 \(Nim\)游戏的改版,我们现在每次最多只能取走\(k\)个石子,那么\(SG\)函数很容易写出来 \[SG(x)=mex_{i=1}^{\min(x,k)}SG( ...

  2. 【BZOJ 3729】3729: Gty的游戏 (Splay维护dfs序+博弈)

    未经博主同意不得转载 3729: Gty的游戏 Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 448  Solved: 150 Descriptio ...

  3. 【BZOJ3729】Gty的游戏,博弈+splay

    传送门 挺蛋疼的一道题 连想带做搞了一晚上晚自习+下午两节课 博弈方面还是很好弄的,就是"阶梯问题"+"Nim取模游戏" 分别维护深度为奇数和偶数的节点的sg函 ...

  4. BZOJ 3729: Gty的游戏

    这两三天貌似没怎么写blog 来补点 劲啊 这道题 我的数据结构真心菜.. 首先对于子树来搞 显然就是用dfs序 由于动态加点 我们用splay 考虑博弈 距离这层为偶数层的可以不管 奇数层的就像简单 ...

  5. BZOJ 3729: Gty的游戏 [伪ETT 博弈论]【学习笔记】

    题意: 给定一棵有根树,每个节点有一些石子,每次可以将不多于k的石子移动到父节点 修改一个点的石子数,插入一个点,询问某棵子树是否先手必胜 显然是一个阶梯Nim 每次最多取k个,找规律或者观察式子易发 ...

  6. 博弈论题表(好少~~~)

    bzoj2017:[Usaco2009 Nov]硬币游戏 *用了一小点思想的傻逼dp(记忆化搜索) bzoj1188:[HNOI2007]分裂游戏 **很神奇的把游戏拆分为子游戏的方法 bzoj102 ...

  7. 伍六七带你学算法 进阶篇-生命游戏

    有趣的算法题–生命游戏 难度-中等 根据 百度百科 ,生命游戏,简称为生命,是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机. 想要体验生命游戏的小伙伴可以到这里-->生命游戏 进入 ...

  8. 自制青蛙跳台阶小游戏~

    青蛙跳台阶小游戏 1.概念(concept)文档 楔子(Setting):千百年来,人们在贬低别人时,常用井底之蛙来描述那个人,但这却让青蛙不开心了,于是青蛙决定跳出井底,为自己讨一个公道. 玩法(G ...

  9. 用Construct 2制作入门小游戏~

    今天在软导课上了解到了Construct 2这个神器,本零基础菜鸟决定尝试做一个简单的小游戏(实际上是入门的教程啊= = 首先呢,肯定是到官网下载软件啊,点击我下载~ 等安装完毕后我便按照新手教程开始 ...

最新文章

  1. 使用MyBatis简化枚举类值的存储和读取
  2. softAP配网:用Android手机为linux无屏设备输入wifi密码
  3. Lind.DDD.DynamicModules动态模块化的设计
  4. 最高科技——疯狂的前缀和
  5. 树莓派slam_SLAM+语音机器人DIY系列:(五)树莓派3开发环境搭建——6.树莓派USB与tty串口号绑定...
  6. mysql通过命令创建数据库和导入数据库
  7. 技术解密|阿里云多媒体 AI 团队是凭借什么拿下 CVPR2021 5冠1亚的?
  8. MyBatis-Plus通用枚举自动关联注入
  9. c+调用java编写mq_C语言实现mq收发数据的函数
  10. 【转】详解:oracle10G 数据库名、实例名、ORACLE_SID
  11. php 获取alexa排名
  12. kali虚拟机分辨率设置
  13. 北理工慕课 嵩天 Python零基础入门 笔记整理
  14. Pandas库的基本使用方法
  15. 高并发,我把握不住啊!
  16. Windows 下编译 OpenSSL
  17. The NTVDM CPU has encountered an illegal instruction. CS:0006 IP:130a ....
  18. CNN实现训练自己的图片数据集
  19. 求1!+2!+....+10!
  20. iPad上支持手柄的游戏推荐 - PUSDN

热门文章

  1. 中英文简历制作注意点
  2. 【Linux4.1.12源码分析】VXLAN报文内核协议栈处理
  3. 抽象类和接口的详解(实例)
  4. [从头读历史] 第283节 神之物语 从克里特岛到底比斯
  5. 模拟炒股大赛怎么玩?看这里!
  6. matlab施加阶跃相应,(基于MATLAB的系统的时域响应分析)(最终版)最新版
  7. 12306所有车次及时刻表的爬取下
  8. wordpress-时光轴风格niconiconi极简清爽主题模板
  9. django-debug-toolbar
  10. 模型违约概率到信用评分的转化