【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

 

posted @ 2015-01-24 14:11  Tunix  阅读(334)  评论(0编辑  收藏  举报