【BZOJ2019】nim
直播写题这刺激233
原题:
著名游戏设计师vfleaking,最近迷上了Nim。普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取。谁不能取谁输。这个游戏是有必胜策略的。于是vfleaking决定写一个玩Nim游戏的平台来坑玩家。
为了设计漂亮一点的初始局面,vfleaking用以下方式来找灵感:拿出很多石子,把它们聚成一堆一堆的,对每一堆编号1,2,3,4,...n,在堆与堆间连边,没有自环与重边,从任意堆到任意堆都只有唯一一条路径可到达。然后他不停地进行如下操作:
1.随机选两个堆v,u,询问若在v到u间的路径上的石子堆中玩Nim游戏,是否有必胜策略,如果有,vfleaking将会考虑将这些石子堆作为初始局面之一,用来坑玩家。
2.把堆v中的石子数变为k。
由于vfleaking太懒了,他懒得自己动手了。请写个程序帮帮他吧。
1≤N≤500000, 1≤Q≤500000、
丧心病狂辣鸡出题人卡dfs_QAQ
如果不卡dfs我不到30min就A了QAQ
平时也没啥,这次是直播啊QAQ(虽然没啥人看
第一次用栈模拟dfs,写挂了好多地方……
主要就是异或满足分配率:a^b^c=a^(b^c),所以就可以直接线段树维护,修改是单点的也不用想那么多
注意栈模拟dfs别写挂,其中关于size的处理坑了我好久,因为在标准dfs中size是儿子dfs完后直接更新当前点的size
但是用手写栈模拟的时候需要先把所有儿子都装进栈再遍历到这个儿子
这就比较蛋疼了,我脑补了一下只会先把遍历到的点存到队列里,然后逆序遍历队列把当前size贡献到father的size里(就像后缀自动姬那样
差点直播翻车,还好最后A掉了qwq
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int rd(){int z=,mk=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')mk=-; ch=getchar();}
while(ch>=''&&ch<=''){z=(z<<)+(z<<)+ch-''; ch=getchar();}
return z*mk;
}
struct ddd{int nxt,y;}e[]; int lk[],ltp=;
inline void ist(int x,int y){ e[++ltp].nxt=lk[x],lk[x]=ltp,e[ltp].y=y;}
int n,m,a[];
int sz[],fth[],dp[],tp[],hvchd[];
int dfsod[],rvsod[],odcnt=;
int v[];
int stck[],quq=;
int q[],hd=;
/*void dfs1(int x){
int mx=0; sz[x]=1;
for(int i=lk[x];i;i=e[i].nxt)if(e[i].y!=fth[x]){
fth[e[i].y]=x,dp[e[i].y]=dp[x]+1; dfs1(e[i].y);
sz[x]+=sz[e[i].y];
if(sz[e[i].y]>mx) mx=sz[e[i].y],hvchd[x]=e[i].y;
}
}*/
void dfs1(){
stck[quq=]=; int x,mx;
while(quq){
x=stck[quq--]; sz[x]=; q[++hd]=x;
for(int i=lk[x];i;i=e[i].nxt)if(e[i].y!=fth[x]){
fth[e[i].y]=x,dp[e[i].y]=dp[x]+; stck[++quq]=e[i].y;
}
}
for(int k=hd;k;--k) sz[fth[q[k]]]+=sz[q[k]];
stck[quq=]=;
while(quq){
x=stck[quq--]; mx=;
for(int i=lk[x];i;i=e[i].nxt)if(e[i].y!=fth[x])
if(sz[e[i].y]>mx) mx=sz[e[i].y],hvchd[x]=e[i].y;
for(int i=lk[x];i;i=e[i].nxt)if(e[i].y!=fth[x])
stck[++quq]=e[i].y;
}
}
/*void dfs2(int x){
dfsod[++odcnt]=x,rvsod[x]=odcnt;
if(hvchd[x]) tp[hvchd[x]]=tp[x],dfs2(hvchd[x]);
for(int i=lk[x];i;i=e[i].nxt)if(e[i].y!=hvchd[x] && e[i].y!=fth[x])
tp[e[i].y]=e[i].y,dfs2(e[i].y);
}*/
void dfs2(){
stck[quq=]=; int x;
while(quq){
x=stck[quq--];
dfsod[++odcnt]=x,rvsod[x]=odcnt;
for(int i=lk[x];i;i=e[i].nxt)if(e[i].y!=hvchd[x] && e[i].y!=fth[x])
tp[e[i].y]=e[i].y,stck[++quq]=e[i].y;
if(hvchd[x]) tp[hvchd[x]]=tp[x],stck[++quq]=hvchd[x];
}
}
void gtsgmttr(int x,int l,int r){
if(l==r){ v[x]=a[dfsod[l]]; return ;}
int md=(l+r)>>;
gtsgmttr(x<<,l,md),gtsgmttr(x<<|,md+,r);
v[x]=v[x<<]^v[x<<|];
}
void mdf(int x,int y,int z,int l,int r){
if(y<l || y>r || l>r) return ;
if(l==r){ v[x]=z; return ;}
int md=(l+r)>>;
if(y<=md) mdf(x<<,y,z,l,md);
else mdf(x<<|,y,z,md+,r);
v[x]=v[x<<]^v[x<<|];
}
int qr(int x,int l,int r,int ll,int rr){
if(l<ll || r>rr || l>r || ll>rr) return ;
if(l==ll && r==rr) return v[x];
int md=(ll+rr)>>;
if(l<=md && r>md) return qr(x<<,l,md,ll,md)^qr(x<<|,md+,r,md+,rr);
else if(r<=md) return qr(x<<,l,r,ll,md);
else return qr(x<<|,l,r,md+,rr);
}
int upupup(int x,int y){
int bwl=,fa=tp[x],fb=tp[y];
while(fa!=fb){
if(dp[fa]<dp[fb]) swap(fa,fb),swap(x,y);
bwl^=qr(,rvsod[fa],rvsod[x],,n);
x=fth[fa],fa=tp[x];
}
if(dp[x]>dp[y]) swap(x,y);
//if(x!=y) bwl^=qr(1,rvsod[x]+1,rvsod[y],1,n);
bwl^=qr(,rvsod[x],rvsod[y],,n);
return bwl;
}
int main(){//freopen("ddd.in","r",stdin);
//freopen("ddd.out","w",stdout);
/*int __size__ = 20 << 20; // 20MB
char *__p__ = (char*)malloc(__size__) + __size__;
__asm__("movl %0, %%esp\n" :: "r"(__p__));*/
cin>>n;
for(int i=;i<=n;++i) a[i]=rd();
int l,r; char s[];
for(int i=;i<n;++i) l=rd(),r=rd(),ist(l,r),ist(r,l);
tp[]=,dfs1(),dfs2(),gtsgmttr(,,n);
cin>>m;
while(m--){
scanf("%s",s); l=rd(),r=rd();
if(s[]=='Q'){
if(upupup(l,r)) printf("Yes\n");
else printf("No\n");
}
else mdf(,rvsod[l],r,,n);
}
//cout<<clock()<<endl;
return ;
}
【BZOJ2019】nim的更多相关文章
- 【HDU3032】Nim or not Nim?(博弈论)
[HDU3032]Nim or not Nim?(博弈论) 题面 HDU 题解 \(Multi-SG\)模板题 #include<iostream> #include<cstdio& ...
- 【BZOJ2819】Nim 树状数组+LCA
[BZOJ2819]Nim Description 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可 ...
- 洛谷 P2197 【模板】nim游戏 解题报告
P2197 [模板]nim游戏 题目描述 甲,乙两个人玩Nim取石子游戏. nim游戏的规则是这样的:地上有n堆石子(每堆石子数量小于10000),每人每次可从任意一堆石子里取出任意多枚石子扔掉,可以 ...
- 【bzoj2819】Nim
Description 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取.谁不能取谁输.这个游 ...
- 【bzoj2819】Nim DFS序+树状数组+倍增LCA
题目描述 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取.谁不能取谁输.这个游戏是有必胜策略 ...
- 【bzoj2819】 Nim
www.lydsy.com/JudgeOnline/problem.php?id=2819 (题目链接) 题意 动态树上路径异或和. Solution Nim取石子游戏的sg值就是每堆石子的异或和,所 ...
- 【POJ】【2068】Nim
博弈论/DP 这是Nim?这不是巴什博奕的变形吗…… 我也不会捉啊,不过一看最多只有20个人,每人最多拿16个石子,总共只有8196-1个石子,范围好像挺小的,嗯目测暴力可做. so,记忆化搜索直接水 ...
- 【POJ】【2975】Nim
博弈论 我哭……思路错误WA了6次?(好像还有手抖点错……) 本题是要求Nim游戏的第一步必胜策略有几种. 一开始我想:先全部异或起来得到ans,从每个比ans大的堆里取走ans个即可,答案如此累计… ...
- 【BZOJ】【2819】NIM
这题……咋说捏,其实是一道披着博弈论外衣的树上操作问题…… 随便用dfs序或者树链剖分转成序列,然后查询路径上的所有点的NIM和(异或和)就行了,毕竟除了是在树上以外,就是裸的NIM问题. 树链剖分: ...
随机推荐
- Javascript this 的一些总结
1.1.1 摘要 相信有C/C++.C#或Java等编程经验的各位,对于this关键字再熟悉不过了.由于Javascript是一种面向对象的编程语言,它和C/C++.C#或Java一样都包含this关 ...
- day16-python常用的内置模块2
logging模块的使用 一:日志是我们排查问题的关键利器,写好日志记录,当我们发生问题时,可以快速定位代码范围进行修改.Python有给我们开发者们提供好的日志模块,下面我们就来介绍一下loggin ...
- vue-router-7-重定向及别名
const router = new VueRouter({ mode: 'history', base: __dirname, routes: [ { path: '/', component: H ...
- ubuntu下修改文件权限
参考:https://www.cnblogs.com/viviwind/archive/2012/08/02/2619451.html 常用方法如下: sudo chmod 600 ××× (只有所有 ...
- countdownlatch 和 CyclicBarrier 和 Semaphore
cdl用的是aqs,共享的是aqs那个volatile的state,阻塞线程列表用的也是aqs的 cb用的是reentrantlock+condition,当然rel用的也是aqs不过不同的是用的是互 ...
- <Parquet><Physical Properties><Best practice><With impala>
Parquet Parquet is a columnar storage format for Hadoop. Parquet is designed to make the advantages ...
- leetcode第27题:移除指定元素
给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成 ...
- 合并k个有序数组
给定K个有序数组,每个数组有n个元素,想把这些数组合并成一个有序数组 可以利用最小堆完成,时间复杂度是O(nklogk),具体过程如下: 创建一个大小为n*k的数组保存最后的结果创建一个大小为k的最小 ...
- 什么是wsgi,uwsgi,uWSGI
WSGI: web服务器网关接口,是一套协议.用于接收用户请求将请求进行初次封装,然后将请求交给web框架 实现wsgi协议的模块: 1,wsgiref,本质就是编写一个socket服务端,用于接收用 ...
- SSH防止超时的设置
针对SSH命令工具超时的解决方法: 1.在命令行输入这两行代码,即可完成 echo export TMOUT=1000000 >> /root/.bash_profile cat /roo ...