bzoj 4034 树上操作 树链剖分 解题报告
来源:互联网 发布:linux 用户安装anconda 编辑:程序博客网 时间:2024/06/07 01:42
Description
有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
Input
第一行包含两个整数 N, M 。表示点数和操作数。接下来一行 N 个整数,表示树中节点的初始权值。接下来 N-1
行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。再接下来 M 行,每行分别表示一次操作。其中
第一个数表示该操作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。
Output
对于每个询问操作,输出该询问的答案。答案之间用换行隔开。
Sample Input
5 5
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
1 2 1
3 5
2 1 2
3 3
Sample Output
6
9
13
HINT
对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不会超过 10^6 。
思路
树链剖分。
线段树单点修改,标准修改;
修改子树的话,DFS序跑一次,修改就好了。
然后树链剖分,修改链。并不用LCA哦。。。
代码
#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int N=100000+5;int n,m,num,head[N],id,pos[N],maxn[N],v[N],bl[N],sized[N],fa[N];long long tag[4*N],sum[4*N];struct edge{ int v,next;}ed[2*N];void build(int u,int v){ ed[++num]=(edge){v,head[u]};head[u]=num; ed[++num]=(edge){u,head[v]};head[v]=num;}void dfs(int x){ sized[x]=1; for (int i=head[x];i;i=ed[i].next) if (ed[i].v!=fa[x]) { fa[ed[i].v]=x; dfs(ed[i].v); sized[x]+=sized[ed[i].v]; maxn[x]=max(maxn[x],maxn[ed[i].v]); }}void dfs2(int x,int chain){ int k=0; bl[x]=chain;pos[x]=maxn[x]=++id; for (int i=head[i];i;i=ed[i].next) if (ed[i].v!=fa[x]&&sized[ed[i].v]>sized[k]) k=ed[i].v; if (k) {dfs2(k,chain);maxn[x]=max(maxn[x],maxn[k]);} for (int i=head[i];i;i=ed[i].next) if (ed[i].v!=fa[x]&&ed[i].v!=k) { dfs2(ed[i].v,ed[i].v); maxn[x]=max(maxn[x],maxn[ed[i].v]); } }void pushdown(int lf,int rt,int k){ if (lf==rt) return ; int mid=(lf+rt)/2; long long t=tag[k]; tag[k]=0; tag[k*2]+=t; tag[k*2+1]+=t; sum[k*2]+=t*(mid-lf+1); sum[k*2+1]+=t*(rt-mid);}void add(int k,int lf,int rt,int x,int y,int val){ if (tag[k]!=0) pushdown(lf,rt,k); if (lf==x&&y==rt) {tag[k]+=val;sum[k]+=(rt-lf+1)*val;return ;} int mid=(lf+rt)/2; if (x<=mid) add(k*2,lf,mid,x,min(mid,y),val); if (y>=mid+1) add(k*2+1,mid+1,rt,max(mid+1,x),y,val); sum[k]=sum[k*2]+sum[k*2+1];}long long query(int k,int lf,int rt,int x,int y){ long long ans=0; if (tag[k]!=0) pushdown(lf,rt,k); if (lf==x&&rt==y) return sum[k]; int mid=(lf+rt)/2; if (x<=mid) ans+=query(k*2,lf,mid,x,min(mid,y)); if (y>=mid+1) ans+=query(k*2+1,mid+1,rt,max(mid+1,x),y); return ans;}long long query(int x){ long long ans=0; while(bl[x]!=1) { ans+=query(1,1,n,pos[bl[x]],pos[x]); x=fa[bl[x]]; } ans+=query(1,1,n,1,pos[x]); return ans;}int main(){ int opt,x,a; scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",&v[i]); for (int i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); build(u,v); } dfs(1); dfs2(1,1); for (int i=1;i<=n;i++) add(1,1,n,pos[i],pos[i],v[i]); while(m--) { scanf("%d%d",&opt,&x); if (opt==1) {scanf("%d",&a);add(1,1,n,pos[x],pos[x],a);} if (opt==2) {scanf("%d",&a);add(1,1,n,pos[x],maxn[x],a);} if (opt==3) printf("%lld\n",query(x)); } return 0;}
阅读全文
2 0
- bzoj 4034 树上操作 树链剖分 解题报告
- 树上操作 解题报告
- bzoj 4034: [HAOI2015]树上操作 (树链剖分)
- 【BZOJ 4034】【HAOI 2015】树上操作【树链剖分】
- 【BZOJ】4034 [HAOI2015]树上操作 树链剖分
- BZOJ 4034 [HAOI2015]树上操作 树链剖分
- 【bzoj 4034】树上操作(树链剖分)
- bzoj 4034: [HAOI2015]树上操作 树链剖分
- BZOJ 3566 [SHOI 2014] 树上期望DP 解题报告
- BZOJ 4034 [HAOI2015]树上操作
- bzoj 4034 [HAOI2015]树上操作
- 【BZOJ 4034】 [HAOI2015]树上操作
- BZOJ 4034: [HAOI2015]树上操作
- BZOJ 4034 树上操作 链剖
- bzoj 4034 [HAOI2015]树上操作
- BZOJ 4034 [HAOI2015]树上操作
- bzoj 1036 树链剖分 解题报告
- |BZOJ 4034|树链剖分|线段树|[HAOI2015]树上操作
- Lintcode 代码
- SpringMVC默认欢迎页面设置为Controller
- iOS storyboard 实现动画,不用将视图拖到代码中
- 前端页面框架-----layerui
- Android启动页,引导页适配华为手机(虚拟按键)显示问题
- bzoj 4034 树上操作 树链剖分 解题报告
- Servlet--获取多个参数值getParameValue(二)
- 1、Angular-Ui Router 状态概要
- 注释转换
- 安装完ubuntu后的一系列配置
- 还有这种操作?(一)
- jdbc和hibernate的区别
- bzoj 3038 上帝造题的七分钟2 (线段树)
- Training LeNet on MNIST with Caffe|保存log绘制accuracy loss曲线