[HDU3966]Aragorn's Story(树链剖分)
2016-02-29 20:58
567 查看
题目描述
传送门题解
树链剖分模板题。有多组数据。代码
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> using namespace std; const int max_n=5e4+5; const int max_e=max_n*2; const int max_N=max_n*4; int w[max_n],h[max_n],father[max_n],son[max_n],size[max_n]; int tree[max_n],num[max_n],top[max_n]; int point[max_n],nxt[max_e],v[max_e],tot; int sum[max_N],delta[max_N]; int n,m,p,f1,f2,u,t,x,y,c,ans,N; inline void clear(){ memset(w,0,sizeof(w)); memset(h,0,sizeof(h)); memset(father,0,sizeof(father)); memset(son,0,sizeof(son)); memset(size,0,sizeof(size)); memset(tree,0,sizeof(tree)); memset(num,0,sizeof(num)); memset(v,0,sizeof(v)); tot=0; memset(sum,0,sizeof(sum)); memset(delta,0,sizeof(delta)); memset(point,0,sizeof(point)); memset(nxt,0,sizeof(nxt)); memset(v,0,sizeof(v)); f1=f2=u=t=x=y=c=ans=N=0; } 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 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; 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){ sum[now]=sum[now<<1]+sum[now<<1|1]; } inline void pushdown(int now,int l,int r,int mid){ if (delta[now]){ sum[now<<1]+=delta[now]*(mid-l+1); delta[now<<1]+=delta[now]; sum[now<<1|1]+=delta[now]*(r-mid); delta[now<<1|1]+=delta[now]; delta[now]=0; } } inline void build(int now,int l,int r){ int mid=(l+r)>>1; if (l==r){ sum[now]=w[tree[l]]; return; } build(now<<1,l,mid); build(now<<1|1,mid+1,r); update(now); } inline void interval_change(int now,int l,int r,int lrange,int rrange,int v){ int mid=(l+r)>>1; if (lrange<=l&&r<=rrange){ sum[now]+=v*(r-l+1); delta[now]+=v; return; } pushdown(now,l,r,mid); if (lrange<=mid) interval_change(now<<1,l,mid,lrange,rrange,v); if (mid+1<=rrange) interval_change(now<<1|1,mid+1,r,lrange,rrange,v); update(now); } inline int query(int now,int l,int r,int x){ int mid=(l+r)>>1,ans=0; if (l==r) return sum[now]; pushdown(now,l,r,mid); if (x<=mid) ans+=query(now<<1,l,mid,x); else ans+=query(now<<1|1,mid+1,r,x); return ans; } inline void ID(int u,int t,int x){ f1=top[u],f2=top[t]; while (f1!=f2){ if (h[f1]<h[f2]){ swap(f1,f2); swap(u,t); } interval_change(1,1,N,num[f1],num[u],x); u=father[f1]; f1=top[u]; } if (num[u]>num[t]) swap(u,t); interval_change(1,1,N,num[u],num[t],x); } int main(){ while (~scanf("%d%d%d",&n,&m,&p)){ clear(); for (int i=1;i<=n;++i) scanf("%d",&w[i]); for (int i=1;i<=m;++i){ scanf("%d%d",&x,&y); add(x,y); } dfs_1(1,0,1); dfs_2(1,0); for (int i=1;i<=n;++i) tree[num[i]]=i; build(1,1,N); for (int i=1;i<=p;++i){ char order=getchar(); while (order!='Q'&&order!='I'&&order!='D') order=getchar(); switch(order){ case 'Q':{ scanf("%d",&c); ans=query(1,1,N,num[c]); printf("%d\n",ans); break; } case 'I':{ scanf("%d%d%d",&u,&t,&x); ID(u,t,x); break; } case 'D':{ scanf("%d%d%d",&u,&t,&x); ID(u,t,-x); break; } } } } }
手写栈
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> using namespace std; const int max_n=5e4+5; const int max_e=max_n*2; const int max_N=max_n*4; int w[max_n],h[max_n],father[max_n],son[max_n],size[max_n]; int tree[max_n],num[max_n],top[max_n]; int point[max_n],nxt[max_e],v[max_e],tot; int sum[max_N],delta[max_N]; int n,m,p,f1,f2,u,t,x,y,c,ans,N; int strack[max_n],cur[max_n],use[max_n]; inline void clear(){ memset(w,0,sizeof(w)); memset(h,0,sizeof(h)); memset(father,0,sizeof(father)); memset(son,0,sizeof(son)); memset(size,0,sizeof(size)); memset(tree,0,sizeof(tree)); memset(num,0,sizeof(num)); memset(v,0,sizeof(v)); tot=0; memset(sum,0,sizeof(sum)); memset(delta,0,sizeof(delta)); memset(point,0,sizeof(point)); memset(nxt,0,sizeof(nxt)); memset(v,0,sizeof(v)); memset(use,0,sizeof(use)); memset(strack,0,sizeof(strack)); memset(cur,0,sizeof(cur)); f1=f2=u=t=x=y=c=ans=N=0; } 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; top[1]=1; num[1]=++N; 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(int now){ sum[now]=sum[now<<1]+sum[now<<1|1]; } inline void pushdown(int now,int l,int r,int mid){ if (delta[now]){ sum[now<<1]+=delta[now]*(mid-l+1); delta[now<<1]+=delta[now]; sum[now<<1|1]+=delta[now]*(r-mid); delta[now<<1|1]+=delta[now]; delta[now]=0; } } inline void build(int now,int l,int r){ int mid=(l+r)>>1; if (l==r){ sum[now]=w[tree[l]]; return; } build(now<<1,l,mid); build(now<<1|1,mid+1,r); update(now); } inline void interval_change(int now,int l,int r,int lrange,int rrange,int v){ int mid=(l+r)>>1; if (lrange<=l&&r<=rrange){ sum[now]+=v*(r-l+1); delta[now]+=v; return; } pushdown(now,l,r,mid); if (lrange<=mid) interval_change(now<<1,l,mid,lrange,rrange,v); if (mid+1<=rrange) interval_change(now<<1|1,mid+1,r,lrange,rrange,v); update(now); } inline int query(int now,int l,int r,int x){ int mid=(l+r)>>1,ans=0; if (l==r) return sum[now]; pushdown(now,l,r,mid); if (x<=mid) ans+=query(now<<1,l,mid,x); else ans+=query(now<<1|1,mid+1,r,x); return ans; } inline void ID(int u,int t,int x){ f1=top[u],f2=top[t]; while (f1!=f2){ if (h[f1]<h[f2]){ swap(f1,f2); swap(u,t); } interval_change(1,1,N,num[f1],num[u],x); u=father[f1]; f1=top[u]; } if (num[u]>num[t]) swap(u,t); interval_change(1,1,N,num[u],num[t],x); } int main(){ while (~scanf("%d%d%d",&n,&m,&p)){ clear(); for (int i=1;i<=n;++i) scanf("%d",&w[i]); for (int i=1;i<=m;++i){ scanf("%d%d",&x,&y); add(x,y); } dfs_1(); dfs_2(); for (int i=1;i<=n;++i) tree[num[i]]=i; build(1,1,N); for (int i=1;i<=p;++i){ char order=getchar(); while (order!='Q'&&order!='I'&&order!='D') order=getchar(); switch(order){ case 'Q':{ scanf("%d",&c); ans=query(1,1,N,num[c]); printf("%d\n",ans); break; } case 'I':{ scanf("%d%d%d",&u,&t,&x); ID(u,t,x); break; } case 'D':{ scanf("%d%d%d",&u,&t,&x); ID(u,t,-x); break; } } } } }
相关文章推荐
- hdu 3966 Aragorn's Story
- 【全排列】next_permutation函数 【algorithm】
- Django学习-01
- 算法代码实现之快速排序,Golang(Go语言)实现
- 我读Mongoose源码----程序框架
- django 模块 template(filter)
- 删除GoldenGate
- mongoengine 查询
- mongoengine 常用类型
- 原创翻译:James Whittaker系列——Google是如何测试的(4)
- 【Google Earth】pro之视频录制
- Leangoo:用敏捷开发管理思维做团队协作的SaaS软件
- 第1周周赛——开学第一课(题解)——出自(Codeforces Good Bye 2015 和 HDU1717)
- Django Xadmin安装
- 下定决心博客搬家(再见csdn,For my oschina!)本博客不再更新,请访问my.oschina.net/tantexian,Thanks dear csdn, goodbye!
- Django 开发服务器启动时发生Error: [Errno 10013] 1错误
- Django~Test View
- Codeforces 196 D. The Next Good String
- go语言值得学习的开源项目推荐
- 安装新版Django