[BZOJ2819]Nim(树链剖分)
2016-05-12 08:20
211 查看
题目描述
传送门题解
为了学手写栈刷了一道水题。线段树+树链剖分维护区间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 =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 =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 =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 =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"); } } }
相关文章推荐
- SkyForm CMP容器化实践
- MTK keypad driver
- UVA 201
- JS操作JSON总结
- CUDA之矩阵乘法——globalmemory
- [麦先生]如何使用AJAX实现按需加载
- SPSS——基本的统计概念
- twitter点赞图标分析
- acpi和btrfs-安装opensuse时的选项
- C#基于Socket的CS模式的完整例子
- Android 横向选择器(HorizontalPickerView.java)
- TCP四步挥手的各种状态转换图
- 真正理解linux的inode?
- Nginx+Tomcat负载均衡配置
- Oracle用户密码过期问题解决
- 纯QML实现画图工具
- P1014
- adapter数据呈现
- 如何做到自律
- ORACLE SQL TUNING ADVISOR 使用方法