BZOJ2819 Nim(DFS序)

题目:单点修改、树链查询。

 

可以直接用树链剖分做。。

修改是O(QlogN),查询是O(QlogNlogN),Q=N=500000;

听说会超时。。

 

这题也可以用DFS序来做。

先不看修改,单单查询:可以求出每个点到根的xor值,那么对任意两点的查询就等于xor(u)^xor(v)^val(lca(u,v));

如果有修改:修改仅仅是单个点,而维护的只是点到根的路径,因此修改仅仅会影响到以这个点为根的子树的所有结点到根的信息。

所以用DFS序把子树们化为连续区间用线段树维护,修改本质上是个线段树的区间修改,查询是个单点查询。

每次修改和查询都是O(logN)。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 #define MAXN 550000
  6 struct Edge{
  7     int v,nxt;
  8 }edge[MAXN<<1];
  9 int NE,head[MAXN];
 10 void addEdge(int u,int v){
 11     edge[NE].v=v; edge[NE].nxt=head[u]; head[u]=NE++;
 12 }
 13 int n,stone[MAXN];
 14 int odr,stack[MAXN],l[MAXN],r[MAXN],dep[MAXN],fa[20][MAXN],val[MAXN];
 15 void dfs(){
 16     int top=0;
 17     stack[++top]=1;
 18     val[1]=stone[1];
 19     while(top){
 20         int u=stack[top];
 21         if(l[u]){
 22             r[u]=odr; --top;
 23             continue;
 24         }
 25         l[u]=++odr;
 26         for(int i=head[u]; i!=-1; i=edge[i].nxt){
 27             int v=edge[i].v;
 28             if(fa[0][u]==v) continue;
 29             fa[0][v]=u; dep[v]=dep[u]+1; val[v]=val[u]^stone[v]; stack[++top]=v;
 30         }
 31     }
 32 }
 33 
 34 int tree[MAXN<<2],N,x,y,z;
 35 void update(int i,int j,int k){
 36     if(x<=i && j<=y){
 37         tree[k]^=z;
 38         return;
 39     }
 40     if(tree[k]){
 41         tree[k<<1]^=tree[k]; tree[k<<1|1]^=tree[k];
 42         tree[k]=0;
 43     }
 44     int mid=i+j>>1;
 45     if(x<=mid) update(i,mid,k<<1);
 46     if(y>mid) update(mid+1,j,k<<1|1);
 47 }
 48 int query(int i,int j,int k){
 49     if(i==j) return tree[k];
 50     if(tree[k]){
 51         tree[k<<1]^=tree[k]; tree[k<<1|1]^=tree[k];
 52         tree[k]=0;
 53     }
 54     int mid=i+j>>1;
 55     if(x<=mid) return query(i,mid,k<<1);
 56     return query(mid+1,j,k<<1|1);
 57 }
 58 
 59 int lca(int u,int v){
 60     if(dep[u]>dep[v]) swap(u,v);
 61     for(int k=0; k<20; ++k){
 62         if((dep[v]-dep[u])>>k&1){
 63             v=fa[k][v];
 64         }
 65     }
 66     if(v==u) return u;
 67     for(int k=19; k>=0; --k){
 68         if(fa[k][u]!=fa[k][v]){
 69             u=fa[k][u];
 70             v=fa[k][v];
 71         }
 72     }
 73     return fa[0][u];
 74 }
 75 void init(){
 76     dfs();
 77     for(int i=1; i<20; ++i){
 78         for(int j=1; j<=n; ++j){
 79             int t=fa[i-1][j];
 80             if(t) fa[i][j]=fa[i-1][t];
 81         }
 82     }
 83     for(N=1; N<odr; N<<=1);
 84     for(int i=1; i<=n; ++i){
 85         x=l[i]; y=l[i]; z=val[i];
 86         update(1,N,1);
 87     }
 88 }
 89 int main(){
 90     int q,a,b;
 91     char op[11];
 92     memset(head,-1,sizeof(head));
 93     scanf("%d",&n);
 94     for(int i=1; i<=n; ++i){
 95         scanf("%d",stone+i);
 96     }
 97     for(int i=1; i<n; ++i){
 98         scanf("%d%d",&a,&b);
 99         addEdge(a,b);
100         addEdge(b,a);
101     }
102     init();
103     scanf("%d",&q);
104     while(q--){
105         scanf("%s%d%d",op,&a,&b);
106         if(op[0]=='Q'){
107             int res;
108             x=l[a]; res=query(1,N,1);
109             x=l[b]; res^=query(1,N,1);
110             res^=stone[lca(a,b)];
111             if(res) puts("Yes");
112             else puts("No");
113         }else{
114             x=l[a]; y=r[a]; z=b^stone[a];
115             update(1,N,1);
116             stone[a]=b;
117         }
118     }
119     return 0;
120 }

 

posted @ 2015-10-17 09:24  WABoss  阅读(666)  评论(0编辑  收藏  举报