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 }