bzoj3729-Gty的游戏【Splay,博弈论】

1|0正题

题目链接:https://darkbzoj.tk/problem/3729


1|1题目大意

给出n个点的一棵树,第i个节点上有ai个石子,然后每次可以选择不超过L个石子移动到父节点处。要求支持操作

  • 以一个节点的子树进行博弈是否有先手必胜
  • 修改一个节点的石子个数
  • 插入一个新的叶子

1n,m5×104,1L109


1|2解题思路

额,首先是阶梯博弈和巴什博弈的缝合怪

巴什博弈结论是石头直接模上一个L+1,然后阶梯博弈要分奇偶深度

然后不带插入的话就是维护dfs序区间的奇数深度和偶数深度的异或和就好了,但是要插入所以要一次改一堆dfs序,所以要用Splay维护就好了。

时间复杂度O(mlogn)


1|3code

#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=2e5+10; struct node{ int to,next; }a[N<<1]; int n,m,L,tot,ls[N],dep[N],v[2][N]; int t[N][2],fa[N],w[2][N],d[N],last; bool Direct(int x) {return t[fa[x]][1]==x;} void PushUp(int x){ if(!x)return; w[0][x]=v[0][x]^w[0][t[x][0]]^w[0][t[x][1]]; w[1][x]=v[1][x]^w[1][t[x][0]]^w[1][t[x][1]]; d[x]=min(dep[x],min(d[t[x][0]],d[t[x][1]])); return; } void Rotate(int x){ int y=fa[x],z=fa[y]; int xs=Direct(x),ys=Direct(y); int w=t[x][xs^1]; t[x][xs^1]=y;t[y][xs]=w; if(z)t[z][ys]=x; if(w)fa[w]=y;fa[y]=x;fa[x]=z; PushUp(y);PushUp(x);return; } void Splay(int x,int f){ while(fa[x]!=f){ int y=fa[x]; if(fa[y]==f)Rotate(x); else if(Direct(x)==Direct(y)) Rotate(y),Rotate(x); else Rotate(x),Rotate(x); } return; } int Find(int x,int k){ if(d[t[x][0]]<=k)Find(t[x][0],k); if(dep[x]<=k)return x; return Find(t[x][1],k); } void addl(int x,int y){ a[++tot].to=y; a[tot].next=ls[x]; ls[x]=tot;return; } void dfs(int x,int F){ t[last][1]=x;fa[x]=last; last=x;dep[x]=dep[F]+1; if(dep[x]&1)swap(v[0][x],v[1][x]); for(int i=ls[x];i;i=a[i].next){ int y=a[i].to; if(y==F)continue; dfs(y,x); } return; } void Downdata(int x) {PushUp(x);if(fa[x])Downdata(fa[x]);return;} int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); scanf("%d%d",&n,&L);d[0]=n+1; for(int i=1;i<=n;i++)scanf("%d",&v[0][i]),v[0][i]%=(L+1); for(int i=1;i<n;i++){ int x,y; scanf("%d%d",&x,&y); addl(x,y);addl(y,x); } last=N-1;d[N-1]=dep[N-1]=n+1; dfs(1,0);t[last][1]=N-2;fa[N-2]=last; last=N-2;d[N-2]=dep[N-2]=n+1; Downdata(last); int sum=0; scanf("%d",&m); for(int i=1;i<=m;i++){ int op,z,x,y; scanf("%d",&op); if(op==1){ scanf("%d",&x);x^=sum; if(i==106) i++,i--; Splay(x,0); if(d[t[x][1]]>dep[x]){ if(w[(dep[x]&1)^1][t[x][1]]) puts("MeiZ"),sum++; else puts("GTY"); } else{ y=Find(t[x][1],dep[x]); Splay(y,x); if(w[(dep[x]&1)^1][t[y][0]]) puts("MeiZ"),sum++; else puts("GTY"); } } else if(op==2){ scanf("%d%d",&x,&y); x^=sum;y^=sum;Splay(x,0); v[dep[x]&1][x]=y%(L+1);PushUp(x); } else if(op==3){ scanf("%d%d%d",&x,&y,&z); z^=sum;x^=sum;y^=sum; dep[y]=dep[x]+1;v[dep[y]&1][y]=z%(L+1); PushUp(y);Splay(x,0); int k=t[x][1];while(t[k][0])k=t[k][0]; Splay(k,x);fa[y]=k;t[k][0]=y; PushUp(k);PushUp(x); } } return 0; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/14797100.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(79)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示