[BZOJ2819]Nim(树链剖分)
来源:互联网 发布:Ubuntu grub引导 编辑:程序博客网 时间:2024/06/03 23:01
题目描述
传送门
题解
为了学手写栈刷了一道水题。
线段树+树链剖分维护区间xor和
代码
递归
#include<iostream>#include<cstring>#include<cstdio>using namespace std;const int max_n=5e5+5;const int max_m=max_n*2;const int max_tree=max_n*4;int n,m,x,y,u,t,ans,q,N,a[max_n];int tot,point[max_n],nxt[max_m],v[max_m];int size[max_n],h[max_n],father[max_n],son[max_n],top[max_n],num[max_n],val[max_n];int tree[max_tree];inline void addedge(int x,int y){ ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; ++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;}inline void dfs_1(int x,int fa,int dep){ size[x]=1; h[x]=dep; father[x]=fa; int maxson=0; for (int i=point[x];i;i=nxt[i]) if (v[i]!=fa) { dfs_1(v[i],x,dep+1); size[x]+=size[v[i]]; if (size[v[i]]>maxson) { maxson=size[v[i]]; son[x]=v[i]; } }}inline void dfs_2(int x,int fa){ if (son[fa]!=x) top[x]=x; else top[x]=top[fa]; num[x]=++N; val[N]=a[x]; if (son[x]) dfs_2(son[x],x); for (int i=point[x];i;i=nxt[i]) if (v[i]!=fa&&v[i]!=son[x]) dfs_2(v[i],x);}inline void update(int now){ tree[now]=tree[now<<1]^tree[now<<1|1];}inline void build(int now,int l,int r){ int mid=(l+r)>>1; if (l==r) { tree[now]=val[l]; return; } build(now<<1,l,mid); build(now<<1|1,mid+1,r); update(now);}inline void point_change(int now,int l,int r,int x,int v){ int mid=(l+r)>>1; if (l==r) { tree[now]=v; return; } if (x<=mid) point_change(now<<1,l,mid,x,v); else point_change(now<<1|1,mid+1,r,x,v); update(now);}inline int query(int now,int l,int r,int lrange,int rrange){ int mid=(l+r)>>1,ans=0; if (lrange<=l&&r<=rrange) return tree[now]; if (lrange<=mid) ans^=query(now<<1,l,mid,lrange,rrange); if (mid+1<=rrange) ans^=query(now<<1|1,mid+1,r,lrange,rrange); return ans;}int main(){ scanf("%d",&n); for (int i=1;i<=n;++i) scanf("%d",&a[i]); for (int i=1;i<n;++i) { scanf("%d%d",&x,&y); addedge(x,y); } dfs_1(1,0,1); dfs_2(1,0); build(1,1,N); scanf("%d",&q); for (int i=1;i<=q;++i) { char opt=getchar(); while (opt!='Q'&&opt!='C') opt=getchar(); if (opt=='C') { scanf("%d%d",&x,&y); point_change(1,1,N,num[x],y); } else { scanf("%d%d",&u,&t); ans=0; int f1=top[u],f2=top[t]; while (f1!=f2) { if (h[f1]<h[f2]) { swap(u,t); swap(f1,f2); } ans^=query(1,1,N,num[f1],num[u]); u=father[f1]; f1=top[u]; } if (num[u]>num[t]) swap(u,t); ans^=query(1,1,N,num[u],num[t]); if (!ans) printf("No\n"); else printf("Yes\n"); } }}
手写栈
#include<iostream>#include<cstring>#include<cstdio>using namespace std;const int max_n=5e5+5;const int max_m=max_n;const int max_e=max_m*2;const int max_tree=max_n*4;int n,m,x,y,u,t,ans,q,N,a[max_n];int tot,point[max_n],nxt[max_e],v[max_e];int size[max_n],h[max_n],father[max_n],son[max_n],top[max_n],num[max_n],val[max_n];int strack[max_n],cur[max_n],use[max_n];int tree[max_tree];inline void addedge(int x,int y){ ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; ++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;}inline void dfs_1(){ int temp=0; h[1]=1; strack[++temp]=1; size[1]=1; for (int i=1;i<=n;++i) cur[i]=point[i]; while (temp) { int x=strack[temp]; if (v[cur[x]]==father[x]) cur[x]=nxt[cur[x]]; if (!cur[x]) { temp--; if (father[x]) { size[father[x]]+=size[x]; if (size[x]>size[son[father[x]]]) son[father[x]]=x; } continue; } int vt=v[cur[x]]; strack[++temp]=vt; size[vt]=1; h[vt]=h[x]+1; father[vt]=x; cur[x]=nxt[cur[x]]; }}inline void dfs_2(){ int temp=0; strack[++temp]=1; top[1]=1; num[1]=++N; val[N]=a[1]; for (int i=1;i<=n;++i) cur[i]=point[i]; while (temp) { int x=strack[temp]; if (!use[x]) { use[x]=1; int vt=son[x]; if (vt) { strack[++temp]=vt; top[vt]=top[x]; num[vt]=++N; val[N]=a[vt]; } continue; } while (cur[x]&&(v[cur[x]]==father[x]||v[cur[x]]==son[x])) cur[x]=nxt[cur[x]]; if (!cur[x]) { temp--; continue; } else { int vt=v[cur[x]]; strack[++temp]=vt; top[vt]=vt; num[vt]=++N; val[N]=a[vt]; cur[x]=nxt[cur[x]]; } }}inline void update(int now){ tree[now]=tree[now<<1]^tree[now<<1|1];}inline void build(int now,int l,int r){ int mid=(l+r)>>1; if (l==r) { tree[now]=val[l]; return; } build(now<<1,l,mid); build(now<<1|1,mid+1,r); update(now);}inline void point_change(int now,int l,int r,int x,int v){ int mid=(l+r)>>1; if (l==r) { tree[now]=v; return; } if (x<=mid) point_change(now<<1,l,mid,x,v); else point_change(now<<1|1,mid+1,r,x,v); update(now);}inline int query(int now,int l,int r,int lrange,int rrange){ int mid=(l+r)>>1,ans=0; if (lrange<=l&&r<=rrange) return tree[now]; if (lrange<=mid) ans^=query(now<<1,l,mid,lrange,rrange); if (mid+1<=rrange) ans^=query(now<<1|1,mid+1,r,lrange,rrange); return ans;}int main(){ scanf("%d",&n); for (int i=1;i<=n;++i) scanf("%d",&a[i]); for (int i=1;i<n;++i) { scanf("%d%d",&x,&y); addedge(x,y); } dfs_1(); dfs_2(); build(1,1,N); scanf("%d",&q); for (int i=1;i<=q;++i) { char opt=getchar(); while (opt!='Q'&&opt!='C') opt=getchar(); if (opt=='C') { scanf("%d%d",&x,&y); point_change(1,1,N,num[x],y); } else { scanf("%d%d",&u,&t); ans=0; int f1=top[u],f2=top[t]; while (f1!=f2) { if (h[f1]<h[f2]) { swap(u,t); swap(f1,f2); } ans^=query(1,1,N,num[f1],num[u]); u=father[f1]; f1=top[u]; } if (num[u]>num[t]) swap(u,t); ans^=query(1,1,N,num[u],num[t]); if (!ans) printf("No\n"); else printf("Yes\n"); } }}
0 0
- [BZOJ2819]Nim(树链剖分)
- 【BZOJ2819】Nim 博弈论+树链剖分
- 【树链剖分】bzoj2819 nim
- Bzoj2819:Nim:树链剖分
- bzoj2819: Nim
- bzoj2819 Nim
- bzoj2819 Nim
- Bzoj2819 Nim
- [bzoj2819]Nim
- 【bzoj2819】 Nim
- 【Bzoj2819】Nim
- 【bzoj2819】Nim
- bzoj2819: Nim
- 【bzoj2819】Nim
- BZOJ2819 Nim
- BZOJ2819 Nim(dfs序+树状数组)
- BZOJ2819 Nim DFS序+BIT+博弈论
- [BZOJ2819] Nim && dfs序 + 树状数组 + LCA
- CUDA之矩阵乘法——globalmemory
- SPSS——基本的统计概念
- SkyForm CMP容器化实践
- UVA 201
- 程序员眼中的古典名画
- [BZOJ2819]Nim(树链剖分)
- js--数组对象的属性方法整理
- 设置Golang的GOPATH
- javaee的EL表达式
- Windows 常用消息大全
- 如何在网页上弹出一个对话框显示一些内容javascript
- 欢迎使用CSDN-markdown编辑器
- ANDROID内存优化(大汇总——全)
- Javase网络通讯(socket编程)群聊系统