BZOJ 4034 T2 (树链剖分解决子树问题)
来源:互联网 发布:python datetime 编辑:程序博客网 时间:2024/06/06 03:26
树链剖分有这样一个性质,即在剖完之后每个结点下面子树的编号一定是连续的,那么基于这一点,我们记录每个结点的区间就能解决子树更新问题
dfs序也可以解决子树问题,但是这里需要计算一个贡献值,结点的层数不好处理。
#include<cstring>#include<iostream>#include<algorithm>#include<cstdio>using namespace std;#define maxn 200004int fir[maxn],nex[maxn],v[maxn],e_max;int in[maxn],out[maxn],son[maxn],fa[maxn],siz[maxn],deep[maxn],top[maxn],tot;long long val[maxn],val1[maxn],sum[2*maxn],tag[2*maxn];void init_(){ memset(fir,-1,sizeof fir); memset(son,-1,sizeof son); e_max=0; tot=1;}void add_edge(int s,int t){ int e=e_max++; v[e]=t; nex[e]=fir[s]; fir[s]=e;}void dfs1(int k,int pre,int d){ deep[k]=d; fa[k]=pre; siz[k]=1; for(int i=fir[k];~i;i=nex[i]) { int e=v[i]; if(e!=pre) { dfs1(e,k,d+1); siz[k]+=siz[e]; if(son[k]==-1||siz[son[k]]<siz[e]) son[k]=e; } }}void dfs2(int k,int sp){ top[k]=sp; in[k]=tot++; out[k]=in[k]; val1[in[k]]=val[k]; if(son[k]==-1) return; dfs2(son[k],sp); out[k]=max(out[k],out[son[k]]); for(int i=fir[k];~i;i=nex[i]) { int e=v[i]; if(e!=fa[k]&&e!=son[k]) { dfs2(e,e); out[k]=max(out[k],out[e]); } }}void init(int l,int r,int k){ tag[k]=0; if(l==r) { sum[k]=val1[l]; return ; } int mid=l+r>>1; init(l,mid,k<<1); init(mid+1,r,k<<1|1); sum[k]=sum[k<<1]+sum[k<<1|1];}void pushdown(int k,int l,int r){ if(!tag[k]) return ; int mid=l+r>>1; tag[k<<1]+=tag[k]; tag[k<<1|1]+=tag[k]; sum[k<<1]+=(mid-l+1)*tag[k]; sum[k<<1|1]+=(r-mid)*tag[k]; tag[k]=0;}void update(int val,int s,int t,int l,int r,int k){ if(s==l&&r==t) { tag[k]+=val; sum[k]+=(long long)(r-l+1)*val; return ; } pushdown(k,l,r); int mid=l+r>>1; if(t<=mid) update(val,s,t,l,mid,k<<1); else if(s>mid) update(val,s,t,mid+1,r,k<<1|1); else update(val,s,mid,l,mid,k<<1),update(val,mid+1,t,mid+1,r,k<<1|1); sum[k]=sum[k<<1]+sum[k<<1|1];}long long query(int s,int t,int l,int r,int k){ if(s==l&&r==t) { return sum[k]; } pushdown(k,l,r); int mid=l+r>>1; if(t<=mid) return query(s,t,l,mid,k<<1); else if(s>mid) return query(s,t,mid+1,r,k<<1|1); else return query(s,mid,l,mid,k<<1)+query(mid+1,t,mid+1,r,k<<1|1);}long long Query(int s,int t){ long long sum=0; int f1=top[s],f2=top[t]; while(f1!=f2) { if(deep[f1]<deep[f2]) swap(f1,f2),swap(s,t); sum+=query(in[f1],in[s],1,tot-1,1); s=fa[f1]; f1=top[s]; } if(deep[s]>deep[t]) swap(s,t); sum+=query(in[s],in[t],1,tot-1,1); return sum;}int main(){ int n,m; while(scanf("%d%d",&n,&m)!=EOF) { init_(); for(int i=1;i<=n;i++) scanf("%lld",&val[i]); for(int i=1;i<n;i++) { int a,b; scanf("%d%d",&a,&b); add_edge(a,b); add_edge(b,a); } dfs1(1,-1,1); dfs2(1,1); init(1,tot-1,1); // for(int i=1;i<=n;i++) cout<<i<<' '<<in[i]<<' '<<out[i]<<' '<<val1[in[i]]<<endl; while(m--) { int op; scanf("%d",&op); if(op==1) { int x,val; scanf("%d%d",&x,&val); update(val,in[x],in[x],1,tot-1,1); } else if(op==2) { int x,val; scanf("%d%d",&x,&val); update(val,in[x],out[x],1,tot-1,1); } else { int x; scanf("%d",&x); long long ans=Query(1,x); printf("%lld\n",ans); } } } return 0;}
0 0
- BZOJ 4034 T2 (树链剖分解决子树问题)
- BZOJ 4034([HAOI2015]T2-树链剖分对子树处理)
- BZOJ-4034 T2 树链剖分
- 树链剖分HLD解决子树问题
- BZOJ 4034 [HAOI2015]T2 树链剖分
- [BZOJ 4034][HAOI2015]T2 [树链剖分]
- BZOJ 4034 [HAOI2015]T2 树链剖分+线段树
- bzoj 4034 [HAOI2015]T2 树链剖分+线段树
- BZOJ 4034: [HAOI2015]T2|线段树|树链剖分
- BZOJ-4034- [HAOI2015]T2-树链剖分+线段树
- bzoj 4034: [HAOI2015]T2
- BZOJ 4034: [HAOI2015]T2
- bzoj 4034 t2
- BZOJ 4034 [HAOI2015]T2
- bzoj 4034 [HAOI2015]T2
- BZOJ 4034: [HAOI2015]T2(树链剖分,点权,线段树)
- BZOJ 4196 软件包管理器(树链剖分子树)
- 4034: [HAOI2015]T2 (树链剖分)
- shell变量基础
- Light oj 1198 Karate Competition 【贪心】
- 深入理解:Android 编译系统
- C++ primer plus 第六版中文版--目录
- html布局所遇到的问题
- BZOJ 4034 T2 (树链剖分解决子树问题)
- shell控制流
- tjut 4308
- Spring学习之旅(2)--Bean容器的初始化
- 异步编程解决方案笔记
- [LightOJ 1364] Expected Cards (高维期望DP)
- PyGobject(六十一)Gtk.Widget
- C等语言各类运算符优先级
- Web即时通讯学习(二)