[BZOJ1036][ZJOI2008]树的统计Count(树链剖分)
2016-02-29 18:55
549 查看
题目描述
传送门题解
树链剖分模板题。代码
// BZOJ 1036 #include<iostream> #include<cstring> #include<cstdio> using namespace std; const int max_n=3e4+5; const int max_e=max_n*4; const int max_N=max_n*4+5; const int mininf=-2100000000; int n,x,y,N,q,u,t,ans,f1,f2; //w[i]表示点i的权值,size[i]表示以i为根的子树的结点个数,h[i]表示点i的深度,father[i]表示点i的父亲,son[i]表示点i的重儿子 int w[max_n],size[max_n],h[max_n],father[max_n],son[max_n]; //top[i]表示点i所在的链的最头上的点,num[i]表示点i在线段树数组中对应的编号,tree[i]表示在线段树数组中编号为i的点在树中对应的点的编号 int top[max_n],num[max_n],tree[max_n]; int point[max_n],next[max_e],v[max_e],tot; char order[10]; int sum[max_N],maxn[max_N]; inline void add(int x,int y){ ++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y; ++tot; next[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=next[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; if (son[x]) dfs_2(son[x],x); for (int i=point[x];i;i=next[i]) if (v[i]!=fa&&v[i]!=son[x]) dfs_2(v[i],x); } inline void update_sum(int now){ sum[now]=sum[now<<1]+sum[now<<1|1]; } inline void update_max(int now){ maxn[now]=max(maxn[now<<1],maxn[now<<1|1]); } inline void build_sum(int now,int l,int r){ int mid=(l+r)>>1; if (l==r){ sum[now]=w[tree[l]]; return; } build_sum(now<<1,l,mid); build_sum(now<<1|1,mid+1,r); update_sum(now); } inline void build_max(int now,int l,int r){ int mid=(l+r)>>1; if (l==r){ maxn[now]=w[tree[l]]; return; } build_max(now<<1,l,mid); build_max(now<<1|1,mid+1,r); update_max(now); } inline void point_change_sum(int now,int l,int r,int x,int v){ int mid=(l+r)>>1; if (l==r){ sum[now]=v; return; } if (x<=mid) point_change_sum(now<<1,l,mid,x,v); else point_change_sum(now<<1|1,mid+1,r,x,v); update_sum(now); } inline void point_change_max(int now,int l,int r,int x,int v){ int mid=(l+r)>>1; if (l==r){ maxn[now]=v; return; } if (x<=mid) point_change_max(now<<1,l,mid,x,v); else point_change_max(now<<1|1,mid+1,r,x,v); update_max(now); } inline int query_sum(int now,int l,int r,int lrange,int rrange){ int mid=(l+r)>>1,ans=0; if (lrange<=l&&r<=rrange) return sum[now]; if (lrange<=mid) ans+=query_sum(now<<1,l,mid,lrange,rrange); if (mid+1<=rrange) ans+=query_sum(now<<1|1,mid+1,r,lrange,rrange); return ans; } inline int query_max(int now,int l,int r,int lrange,int rrange){ int mid=(l+r)>>1,ans=mininf; if (lrange<=l&&r<=rrange) return maxn[now]; if (lrange<=mid) ans=max(ans,query_max(now<<1,l,mid,lrange,rrange)); if (mid+1<=rrange) ans=max(ans,query_max(now<<1|1,mid+1,r,lrange,rrange)); return ans; } int main(){ scanf("%d",&n); for (int i=1;i<n;++i){ scanf("%d%d",&x,&y); add(x,y); } for (int i=1;i<=n;++i) scanf("%d",&w[i]); //预处理size,h,father,son的值 dfs_1(1,0,1); //预处理top,num,tree的值 dfs_2(1,0); for (int i=1;i<=n;++i) tree[num[i]]=i; build_sum(1,1,N); build_max(1,1,N); scanf("%d",&q); for (int i=1;i<=q;++i){ scanf("%s",order); while (strlen(order)<4) scanf("%s",order); scanf("%d%d",&u,&t); if (order[0]=='C'){ point_change_sum(1,1,N,num[u],t); point_change_max(1,1,N,num[u],t); } else{ if (order[1]=='S'){ ans=0; f1=top[u],f2=top[t]; while (f1!=f2){ if (h[f1]<h[f2]){ swap(u,t); swap(f1,f2); } ans+=query_sum(1,1,N,num[f1],num[u]); u=father[f1]; f1=top[u]; } if (num[u]>num[t]) swap(u,t); ans+=query_sum(1,1,N,num[u],num[t]); printf("%d\n",ans); } else{ ans=mininf; f1=top[u],f2=top[t]; while (f1!=f2){ if (h[f1]<h[f2]){ swap(u,t); swap(f1,f2); } ans=max(ans,query_max(1,1,N,num[f1],num[u])); u=father[f1]; f1=top[u]; } if (num[u]>num[t]) swap(u,t); ans=max(ans,query_max(1,1,N,num[u],num[t])); printf("%d\n",ans); } } } }
手写栈
#include<iostream> #include<cstring> #include<cstdio> using namespace std; const int max_n=3e4+5; const int max_e=max_n*4; const int max_N=max_n*4+5; const int mininf=-2100000000; int n,x,y,N,q,u,t,ans,f1,f2; int w[max_n],size[max_n],h[max_n],father[max_n],son[max_n]; int top[max_n],num[max_n],tree[max_n]; int strack[max_n],cur[max_n],use[max_n]; int point[max_n],nxt[max_e],v[max_e],tot; char order[10]; int sum[max_N],maxn[max_N]; inline void add(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; strack[++temp]=1; size[1]=1; h[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; num[1]=++N; top[1]=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; } 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; cur[x]=nxt[cur[x]]; } } } inline void update_sum(int now){ sum[now]=sum[now<<1]+sum[now<<1|1]; } inline void update_max(int now){ maxn[now]=max(maxn[now<<1],maxn[now<<1|1]); } inline void build_sum(int now,int l,int r){ int mid=(l+r)>>1; if (l==r){ sum[now]=w[tree[l]]; return; } build_sum(now<<1,l,mid); build_sum(now<<1|1,mid+1,r); update_sum(now); } inline void build_max(int now,int l,int r){ int mid=(l+r)>>1; if (l==r){ maxn[now]=w[tree[l]]; return; } build_max(now<<1,l,mid); build_max(now<<1|1,mid+1,r); update_max(now); } inline void point_change_sum(int now,int l,int r,int x,int v){ int mid=(l+r)>>1; if (l==r){ sum[now]=v; return; } if (x<=mid) point_change_sum(now<<1,l,mid,x,v); else point_change_sum(now<<1|1,mid+1,r,x,v); update_sum(now); } inline void point_change_max(int now,int l,int r,int x,int v){ int mid=(l+r)>>1; if (l==r){ maxn[now]=v; return; } if (x<=mid) point_change_max(now<<1,l,mid,x,v); else point_change_max(now<<1|1,mid+1,r,x,v); update_max(now); } inline int query_sum(int now,int l,int r,int lrange,int rrange){ int mid=(l+r)>>1,ans=0; if (lrange<=l&&r<=rrange) return sum[now]; if (lrange<=mid) ans+=query_sum(now<<1,l,mid,lrange,rrange); if (mid+1<=rrange) ans+=query_sum(now<<1|1,mid+1,r,lrange,rrange); return ans; } inline int query_max(int now,int l,int r,int lrange,int rrange){ int mid=(l+r)>>1,ans=mininf; if (lrange<=l&&r<=rrange) return maxn[now]; if (lrange<=mid) ans=max(ans,query_max(now<<1,l,mid,lrange,rrange)); if (mid+1<=rrange) ans=max(ans,query_max(now<<1|1,mid+1,r,lrange,rrange)); return ans; } int main(){ scanf("%d",&n); for (int i=1;i<n;++i){ scanf("%d%d",&x,&y); add(x,y); } for (int i=1;i<=n;++i) scanf("%d",&w[i]); dfs_1(); dfs_2(); for (int i=1;i<=n;++i) tree[num[i]]=i; build_sum(1,1,N); build_max(1,1,N); scanf("%d",&q); for (int i=1;i<=q;++i){ scanf("%s",order); scanf("%d%d",&u,&t); if (order[0]=='C'){ point_change_sum(1,1,N,num[u],t); point_change_max(1,1,N,num[u],t); } else{ if (order[1]=='S'){ ans=0; f1=top[u],f2=top[t]; while (f1!=f2){ if (h[f1]<h[f2]){ swap(u,t); swap(f1,f2); } ans+=query_sum(1,1,N,num[f1],num[u]); u=father[f1]; f1=top[u]; } if (num[u]>num[t]) swap(u,t); ans+=query_sum(1,1,N,num[u],num[t]); printf("%d\n",ans); } else{ ans=mininf; f1=top[u],f2=top[t]; while (f1!=f2){ if (h[f1]<h[f2]){ swap(u,t); swap(f1,f2); } ans=max(ans,query_max(1,1,N,num[f1],num[u])); u=father[f1]; f1=top[u]; } if (num[u]>num[t]) swap(u,t); ans=max(ans,query_max(1,1,N,num[u],num[t])); printf("%d\n",ans); } } } }
总结
①线段树要开4n,不要开2n②线段树的操作可以合并
相关文章推荐
- IOS 将数组转化成NSData数据进行保存
- ACM_模板_母函数
- vps安全设置
- linux服务器上设置多主机头,设置多web站点
- The repository for high quality TypeScript type definitions
- bean的初始化过程和对应源代码
- less
- IOS开发之UIView总结
- uva10271 经典DP
- hiredis aeStop仅在redis命令的回调函数中生效 分析
- 大数据之一:几个概念
- [Android] 怎么在应用中实现密码隐藏?
- TI DSP TMS320C66x学习笔记之SPI Nor Flash多核程序烧写(七)
- maven之伺服仓库
- 奕新集团---单实例到RAC11g生产环境搭建(无图)
- 多线程--GCD
- io_service work 的作用
- WPF 支持分组互斥的 RadioButton 式单选菜单
- socket http文件下载器c语言实现
- Gallery2 让图库不显示bmp格式图片