BZOJ2819 Nim(DFS序)
生活随笔
收集整理的這篇文章主要介紹了
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 }?
轉載于:https://www.cnblogs.com/WABoss/p/4886918.html
總結
以上是生活随笔為你收集整理的BZOJ2819 Nim(DFS序)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【VS开发】CTimeSpan类
- 下一篇: memcache中的add和set方法区