【BZOJ】2819: Nim(树链剖分 / lca+dfs序+树状数组)
题目
传送门:QWQ
分析
先敲了个树链剖分,发现无法AC(其实是自己弱,懒得debug、手写栈)
然后去学了学正解
核心挺好理解的,$ query(a) $是$ a $到根的异或和。
答案就是$ lca(x,y) \hat{} query(x) \hat{} query(b) $
接着维护异或和,很显然线段树挺容易搞的。
但我们今天学学树状数组来维护异或和
若将区间$ [l,r] $内的元素全部异或x,相当于在第l位标记x,再在第r+1位标记x,
这样,对于第r位以后的元素,这两个命令互相抵消,查询某个元素的值,只需用树状数组把它之前的命令全部累加起来即可。
强无敌了~~~
代码
lca+dfs序+树状数组:
#include <bits/stdc++.h> using namespace std; const int maxn=500005; int fa[maxn][20],depth[maxn],w[maxn]; int in[maxn],out[maxn],cnt,vis[maxn],n,bit[maxn]; vector<int> G[maxn]; int dfs(int u){ for(int i=1;i<19;i++){ if(depth[u] < (1 << i)) break; fa[u][i]=fa[fa[u][i-1]][i-1]; } in[u]=++cnt; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(vis[v]) continue; vis[v]=1; fa[v][0]=u; depth[v]=depth[u]+1; dfs(v); } out[u]=cnt; } int lca(int x,int y){ if(depth[x]<depth[y]) swap(x,y); int d=(depth[x]-depth[y]); for(int i=0;i<19;i++){ if((1<<i) & d) x=fa[x][i]; } for(int i=18;i>=0;i--){ if(fa[x][i]!=fa[y][i]){ x=fa[x][i]; y=fa[y][i]; } } if(x==y) return x; else return fa[x][0]; } void add(int x,int v){for(;x<=n;x+=x&-x) bit[x]^=v;} int query(int x){int ans=0;for(;x>0;x-=x&-x) ans^=bit[x];return ans;} int main() { int u,v,q; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&w[i]); for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); G[u].push_back(v);G[v].push_back(u); } vis[1]=1;dfs(1); for(int i=1;i<=n;i++){ add(in[i],w[i]); add(out[i]+1,w[i]); } scanf("%d",&q); int a,b; char s[10]; while(q--){ scanf("%s%d%d",s,&a,&b); if(s[0]=='Q'){ int ans=w[lca(a,b)]^query(in[a])^query(in[b]); if(ans!=0) puts("Yes"); else puts("No"); // printf("--------------- %d %d %d\n",lca(a,b),query(in[a]),query(in[b])); } else{ add(in[a],w[a]);add(out[a]+1,w[a]); w[a]=b; add(in[a],w[a]);add(out[a]+1,w[a]); } } return 0; } /* 8 1 3 5 2 5 3 1 1 1 5 3 5 2 5 1 4 6 3 7 4 8 3 13 Q 1 2 Q 3 5 Q 1 8 Q 3 5 Q 6 2 C 2 5 C 4 6 C 8 5 Q 1 2 Q 3 5 Q 1 8 Q 3 5 Q 6 2 */
树链剖分(无法AC):
#include <bits/stdc++.h> using namespace std; const int maxn=500005; int top[maxn],fa[maxn],son[maxn],dep[maxn],siz[maxn]; int wt[2*maxn],w[2*maxn],id[2*maxn],v[2*maxn],cnt,n; vector<int> G[maxn]; void build(int o,int l,int r){ if(l==r){ v[o]=wt[l]; return; } int mid=l+r>>1; build(o<<1,l,mid); build(o<<1|1,mid+1,r); v[o]=v[o<<1]^v[o<<1|1]; } void update(int o,int l,int r,int val,int L){ // printf("--->>> %d %d %d %d %d\n",o,l,r,val,L); if(l==r){ v[o]=val; return; } int mid=l+r>>1; if(L<=mid) update(o<<1,l,mid,val,L); else update(o<<1|1,mid+1,r,val,L); v[o]=v[o<<1]^v[o<<1|1]; } int query(int o,int l,int r,int L,int R){ if(l>R||r<L) return 0; if(l>=L&&r<=R){return v[o];} int mid=l+r>>1; int ans=query(o<<1,l,mid,L,R)^query(o<<1|1,mid+1,r,L,R); return ans; } /////////////////////////////////////////// int dfs1(int x,int f,int depth){ dep[x]=depth; fa[x]=f; siz[x]=1; int maxnum=0; for(int i=0;i<G[x].size();i++){ int v=G[x][i]; if(v==f) continue; dfs1(v,x,depth+1); siz[x]+=siz[v]; if(maxnum<siz[v]){ maxnum=siz[v]; son[x]=v; } } } void dfs2(int x,int topf){ top[x]=topf; id[x]=++cnt; wt[id[x]]=w[x]; if(!son[x]) return; dfs2(son[x],topf); for(int i=0;i<G[x].size();i++){ int v=G[x][i]; if(v!=son[x]&&v!=fa[x]){ dfs2(v,v); } } } void debug(){ puts("\ndepth: "); for(int i=1;i<=n;i++) printf("%d ",dep[i]); puts("\nson: "); for(int i=1;i<=n;i++) printf("%d ",son[i]); puts("\ntop: "); for(int i=1;i<=n;i++) printf("%d ",top[i]); } int Qu(int x,int y){ int ans=0; for(;top[x]!=top[y];){ if(dep[top[x]]<dep[top[y]]) swap(x,y); ans^=query(1,1,n,id[top[x]],id[x]); x=fa[top[x]]; } if(dep[x]>dep[y]) swap(x,y); ans^=query(1,1,n,id[x],id[y]); return ans; } int main() { // freopen("1.txt","r",stdin); // int __size__=30<<20; // char *__p__=(char*)malloc(__size__)+__size__; // __asm__("movl %0, %%esp\n"::"r"(__p__)); int u,v,q; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&w[i]); for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); G[u].push_back(v);G[v].push_back(u); } dfs1(1,0,1); dfs2(1,1); build(1,1,n); scanf("%d",&q); // printf("====== %d\n",query(1,1,n,1,1)); int a,b; char s[10]; while(q--){ // printf("========= %d\n",q); scanf("%s%d%d",s,&a,&b); if(s[0]=='Q'){ int ans=Qu(a,b); if(ans!=0) puts("Yes"); else puts("No"); } else{ update(1,1,n,b,id[a]); } } // debug(); return 0; } /* 8 1 3 5 2 5 3 1 1 1 5 3 5 2 5 1 4 6 3 7 4 8 3 13 Q 1 2 Q 3 5 Q 1 8 Q 3 5 Q 6 2 C 2 5 C 4 6 C 8 5 Q 1 2 Q 3 5 Q 1 8 Q 3 5 Q 6 2 */