首页 > 代码库 > 【BZOJ】【2819】NIM

【BZOJ】【2819】NIM

这题……咋说捏,其实是一道披着博弈论外衣的树上操作问题……

随便用dfs序或者树链剖分转成序列,然后查询路径上的所有点的NIM和(异或和)就行了,毕竟除了是在树上以外,就是裸的NIM问题。

 

树链剖分:一开始把线段树写跪了,然后输出“Yes”和“No”的时候全部大写了,再然后发现线段树空间开小了……

 

代码如下:

技术分享
  1 //BZOJ 2819  2 #include<cstdio>  3 #include<vector>  4 #include<cstring>  5 #include<cstdlib>  6 #include<iostream>  7 #include<algorithm>  8 #define rep(i,n) for(int i=0;i<n;++i)  9 #define F(i,j,n) for(int i=j;i<=n;++i) 10 #define D(i,j,n) for(int i=j;i>=n;--i) 11 #define pb push_back 12 using namespace std; 13 const int N=500010; 14 #define debug 15 int n,a[N],t[N<<2],fa[N],top[N],dep[N],son[N],size[N],tid[N],cnt=0; 16 vector<int>G[N]; 17 bool vis[N]; 18  19 #define mid (l+r>>1) 20 #define L (o<<1) 21 #define R (o<<1|1) 22 void updata(int o,int l,int r,int pos,int v){ 23     if (l==r) t[o]=v; 24     else{ 25         if (pos<=mid) updata(L,l,mid,pos,v); 26         else updata(R,mid+1,r,pos,v); 27         t[o]=t[L]^t[R]; 28     } 29 } 30  31 int ql,qr,ans=0; 32 void query_it(int o,int l,int r){ 33     if (ql<=l && qr>=r) ans^=t[o]; 34     else{ 35         if (ql<=mid) query_it(L,l,mid); 36         if (qr>mid) query_it(R,mid+1,r); 37     } 38 } 39 //segment tree end 40  41 void dfs(int x,int f,int deep){ 42     int y,maxsize=0; 43     vis[x]=1; fa[x]=f; dep[x]=deep; size[x]=1; son[x]=0; 44     rep(i,G[x].size()){ 45         y=G[x][i]; 46         if (vis[y]) continue; 47         dfs(y,x,deep+1); 48         size[x]+=size[y]; 49         if (size[y]>maxsize) maxsize=size[y],son[x]=y; 50     } 51 } 52  53 void connect(int x,int f){ 54     tid[x]=++cnt; 55     top[x]=f; vis[x]=1; 56     if (son[x]) connect(son[x],f); 57     rep(i,G[x].size()){ 58         int y=G[x][i]; 59         if (!vis[y]) connect(y,y); 60     } 61 } 62  63 void query(int x,int y){ 64     while(top[x]!=top[y]){ 65         if (dep[top[x]]<dep[top[y]]) swap(x,y); 66         ql=tid[top[x]]; qr=tid[x]; 67         query_it(1,1,n); 68         x=fa[top[x]]; 69     } 70     if (dep[x]>dep[y]) swap(x,y); 71     ql=tid[x]; qr=tid[y]; 72     query_it(1,1,n); 73 } 74  75 int main(){ 76 //    freopen("file.in","r",stdin); 77     scanf("%d",&n); 78     F(i,1,n) scanf("%d",&a[i]); 79     int x,y; 80     F(i,2,n){ 81         scanf("%d%d",&x,&y); 82         G[x].pb(y); 83         G[y].pb(x); 84     } 85     dfs(1,0,1); 86     memset(vis,0,sizeof vis); 87     connect(1,1); 88     F(i,1,n) updata(1,1,n,tid[i],a[i]); 89     int q; 90     scanf("%d",&q); 91     char cmd[3]; 92     F(i,1,q){ 93         scanf("%s%d%d",cmd,&x,&y); 94         if (cmd[0]==Q){ 95             ans=0; 96             query(x,y); 97             printf(ans ? "Yes\n" : "No\n"); 98         } 99         else updata(1,1,n,tid[x],y);100     }101     return 0;102 }
View Code

 

dfs序版:

维护从根到x的异或和sum(x),则query(x,y)=sum(x)^sum(y)^a[lca(x,y)]

自己画个图一眼就看出来了……公共部分两次异或互相抵消,但是LCA是在x-->y这条路径上的,所以要再加上

技术分享
  1 /**************************************************************  2     Problem: 2819  3     User: Tunix  4     Language: C++  5     Result: Accepted  6     Time:15004 ms  7     Memory:65740 kb  8 ****************************************************************/  9   10 //BZOJ 2819 11 #include<cmath> 12 #include<cstdio> 13 #include<cstring> 14 #include<cstdlib> 15 #include<iostream> 16 #include<algorithm> 17 #define rep(i,n) for(int i=0;i<n;++i) 18 #define F(i,j,n) for(int i=j;i<=n;++i) 19 #define D(i,j,n) for(int i=j;i>=n;--i) 20 using namespace std; 21 void read(int &v){ 22     v=0; int sign=1; char ch=getchar(); 23     while(ch<0||ch>9){ if (ch==-) sign=-1; ch=getchar();} 24     while(ch>=0&&ch<=9){ v=v*10+ch-0; ch=getchar();} 25     v*=sign; 26 } 27 /******************tamplate*********************/ 28 const int N=500010; 29 int head[N],to[N<<1],next[N<<1],cnt,fa[N]; 30 void add(int x,int y){ 31     to[++cnt]=y; next[cnt]=head[x]; head[x]=cnt; 32     to[++cnt]=x; next[cnt]=head[y]; head[y]=cnt; 33 } 34 /*******************edge***********************/ 35 int n,m,dfs_clock,l[N],r[N],t[N<<1],a[N],deep[N]; 36 int st[N],top; 37 void dfs(){ 38     st[++top]=1; fa[1]=0;deep[1]=1; 39     while(top){ 40         int x=st[top]; 41         if (!l[x]){ 42             l[x]=++dfs_clock; 43             for(int i=head[x];i;i=next[i]) 44                 if (to[i]!=fa[x]){ 45                     st[++top]=to[i]; 46                     fa[to[i]]=x; 47                     deep[to[i]]=deep[x]+1; 48                 } 49         } 50         else{ 51             r[x]=++dfs_clock; 52             top--; 53         } 54     } 55 } 56 int p[N][20]; 57 void ST(){ 58     memset(p,-1,sizeof p); 59     F(i,1,n) p[i][0]=fa[i]; 60     for(int j=1;(1<<j)<=n;++j) 61         F(i,1,n) 62             if (p[i][j-1]!=-1) p[i][j]=p[p[i][j-1]][j-1]; 63 } 64 int lca(int x,int y){ 65     if (deep[x]<deep[y]) swap(x,y); 66     int k=log(deep[x])/log(2); 67     D(i,k,0) 68         if (deep[x]-(1<<i)>=deep[y]) x=p[x][i]; 69     if (x==y) return y; 70     D(i,k,0) 71         if (p[x][i]!=-1 && p[x][i]!=p[y][i]){ 72             x=p[x][i]; y=p[y][i]; 73         } 74     return p[x][0]; 75 } 76 /*****************dfs&LCA***********************/ 77 inline int lowbit(int x){return x&(-x);} 78 void update(int x,int val){ 79     for(x;x<=n*2;x+=lowbit(x)) t[x]^=val; 80 } 81 int sum(int x){ 82     int temp=0; 83     for(x;x;x-=lowbit(x)) temp^=t[x]; 84     return temp; 85 } 86 /*********************fenwick*******************/ 87 int main(){ 88     read(n); 89     F(i,1,n) read(a[i]); 90     int x,y; 91     F(i,2,n){ 92         read(x); read(y); 93         add(x,y); 94     } 95     dfs(); 96     ST(); 97     F(i,1,n) update(l[i],a[i]),update(r[i],a[i]); 98     read(m); 99     char cmd[5];100     F(i,1,m){101         scanf("%s",cmd);102         read(x); read(y);103         if (cmd[0]==Q) printf( sum(l[y])^sum(l[x])^a[lca(x,y)] ? "Yes\n" : "No\n");104         else{105             update(l[x],a[x]); update(r[x],a[x]);106             update(l[x],y); update(r[x],y);107             a[x]=y;108         }109     }110     return 0;111 }
View Code

 

【BZOJ】【2819】NIM