码迷,mamicode.com
首页 > 其他好文 > 详细

【BZOJ2019】nim

时间:2017-03-14 22:36:21      阅读:223      评论:0      收藏:0      [点我收藏+]

标签:需要   str   线段树   遍历   print   end   stc   math   dfs   

直播写题这刺激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

代码:

技术分享
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 using namespace std;
  7 int rd(){int z=0,mk=1;  char ch=getchar();
  8     while(ch<0||ch>9){if(ch==-)mk=-1;  ch=getchar();}
  9     while(ch>=0&&ch<=9){z=(z<<3)+(z<<1)+ch-0;  ch=getchar();}
 10     return z*mk;
 11 }
 12 struct ddd{int nxt,y;}e[1100000];  int lk[510000],ltp=0;
 13 inline void ist(int x,int y){  e[++ltp].nxt=lk[x],lk[x]=ltp,e[ltp].y=y;}
 14 int n,m,a[510000];
 15 int sz[510000],fth[510000],dp[510000],tp[510000],hvchd[510000];
 16 int dfsod[510000],rvsod[510000],odcnt=0;
 17 int v[2100000];
 18 int stck[510000],quq=0;
 19 int q[510000],hd=0;
 20 /*void dfs1(int x){
 21     int mx=0;  sz[x]=1;
 22     for(int i=lk[x];i;i=e[i].nxt)if(e[i].y!=fth[x]){
 23         fth[e[i].y]=x,dp[e[i].y]=dp[x]+1;  dfs1(e[i].y);
 24         sz[x]+=sz[e[i].y];
 25         if(sz[e[i].y]>mx)  mx=sz[e[i].y],hvchd[x]=e[i].y;
 26     }
 27 }*/
 28 void dfs1(){
 29     stck[quq=1]=1;  int x,mx;
 30     while(quq){
 31         x=stck[quq--];  sz[x]=1;  q[++hd]=x;
 32         for(int i=lk[x];i;i=e[i].nxt)if(e[i].y!=fth[x]){
 33             fth[e[i].y]=x,dp[e[i].y]=dp[x]+1;  stck[++quq]=e[i].y;
 34         }
 35     }
 36     for(int k=hd;k;--k)  sz[fth[q[k]]]+=sz[q[k]];
 37     stck[quq=1]=1;
 38     while(quq){
 39         x=stck[quq--];  mx=0;
 40         for(int i=lk[x];i;i=e[i].nxt)if(e[i].y!=fth[x])
 41             if(sz[e[i].y]>mx)  mx=sz[e[i].y],hvchd[x]=e[i].y;
 42         for(int i=lk[x];i;i=e[i].nxt)if(e[i].y!=fth[x])
 43             stck[++quq]=e[i].y;
 44     }
 45 }
 46 /*void dfs2(int x){
 47     dfsod[++odcnt]=x,rvsod[x]=odcnt;
 48     if(hvchd[x])  tp[hvchd[x]]=tp[x],dfs2(hvchd[x]);
 49     for(int i=lk[x];i;i=e[i].nxt)if(e[i].y!=hvchd[x] && e[i].y!=fth[x])
 50         tp[e[i].y]=e[i].y,dfs2(e[i].y);
 51 }*/
 52 void dfs2(){
 53     stck[quq=1]=1;  int x;
 54     while(quq){
 55         x=stck[quq--];
 56         dfsod[++odcnt]=x,rvsod[x]=odcnt;
 57         for(int i=lk[x];i;i=e[i].nxt)if(e[i].y!=hvchd[x] && e[i].y!=fth[x])
 58             tp[e[i].y]=e[i].y,stck[++quq]=e[i].y;
 59         if(hvchd[x])  tp[hvchd[x]]=tp[x],stck[++quq]=hvchd[x];
 60     }
 61 }
 62 void gtsgmttr(int x,int l,int r){
 63     if(l==r){  v[x]=a[dfsod[l]];  return ;}
 64     int md=(l+r)>>1;
 65     gtsgmttr(x<<1,l,md),gtsgmttr(x<<1|1,md+1,r);
 66     v[x]=v[x<<1]^v[x<<1|1];
 67 }
 68 void mdf(int x,int y,int z,int l,int r){
 69     if(y<l || y>r || l>r)  return ;
 70     if(l==r){  v[x]=z;  return ;}
 71     int md=(l+r)>>1;
 72     if(y<=md)  mdf(x<<1,y,z,l,md);
 73     else  mdf(x<<1|1,y,z,md+1,r);
 74     v[x]=v[x<<1]^v[x<<1|1];
 75 }
 76 int qr(int x,int l,int r,int ll,int rr){
 77     if(l<ll || r>rr || l>r || ll>rr)  return 0;
 78     if(l==ll && r==rr)  return v[x];
 79     int md=(ll+rr)>>1;
 80     if(l<=md && r>md)  return qr(x<<1,l,md,ll,md)^qr(x<<1|1,md+1,r,md+1,rr);
 81     else if(r<=md)  return qr(x<<1,l,r,ll,md);
 82     else  return qr(x<<1|1,l,r,md+1,rr);
 83 }
 84 int upupup(int x,int y){
 85     int bwl=0,fa=tp[x],fb=tp[y];
 86     while(fa!=fb){
 87         if(dp[fa]<dp[fb])  swap(fa,fb),swap(x,y);
 88         bwl^=qr(1,rvsod[fa],rvsod[x],1,n);
 89         x=fth[fa],fa=tp[x];
 90     }
 91     if(dp[x]>dp[y])  swap(x,y);
 92     //if(x!=y)  bwl^=qr(1,rvsod[x]+1,rvsod[y],1,n);
 93     bwl^=qr(1,rvsod[x],rvsod[y],1,n);
 94     return bwl;
 95 }
 96 int main(){//freopen("ddd.in","r",stdin);
 97     //freopen("ddd.out","w",stdout);
 98 /*int __size__ = 20 << 20; // 20MB
 99 char *__p__ = (char*)malloc(__size__) + __size__;
100 __asm__("movl %0, %%esp\n" :: "r"(__p__));*/
101     cin>>n;
102     for(int i=1;i<=n;++i)  a[i]=rd();
103     int l,r;  char s[2];
104     for(int i=1;i<n;++i)  l=rd(),r=rd(),ist(l,r),ist(r,l);
105     tp[1]=1,dfs1(),dfs2(),gtsgmttr(1,1,n);
106     cin>>m;
107     while(m--){
108         scanf("%s",s);  l=rd(),r=rd();
109         if(s[0]==Q){
110             if(upupup(l,r))  printf("Yes\n");
111             else  printf("No\n");
112         }
113         else  mdf(1,rvsod[l],r,1,n);
114     }
115     //cout<<clock()<<endl;
116     return 0;
117 }
View Code

 

【BZOJ2019】nim

标签:需要   str   线段树   遍历   print   end   stc   math   dfs   

原文地址:http://www.cnblogs.com/JSL2018/p/6551005.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!