【HAOI2015】树上操作(树链剖分)
来源:互联网 发布:四年级英语辅导软件 编辑:程序博客网 时间:2024/06/16 04:04
题面
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
数据范围:
对于30%的数据,N,M<=1000。
对于50%的数据,N,M<=100000且数据随机。
对于100%的数据,N,M<=100000,且所有输入数据的绝对值都不会超过10^6。
题解
依旧是很显然的树链剖分,要用longlong存答案
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<queue>#include<vector>#include<algorithm>using namespace std;#define MAX 101000#define lson (now<<1)#define rson ((now<<1)|1)inline int read(){ register int x=0,t=1; register char ch=getchar(); while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar(); if(ch=='-'){t=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} return x*t;}struct Line{ int v,next;}e[MAX*2];struct Node{ long long v,lazy;}c[MAX*5];int h[MAX],cnt=1,tim,V[MAX];int dfn[MAX],low[MAX],f[MAX],hson[MAX],line[MAX],size[MAX],top[MAX];int N,Q,dep[MAX];inline void Add(int u,int v){ e[cnt]=(Line){v,h[u]}; h[u]=cnt++;}void DFS1(int u,int ff){ size[u]=1;f[u]=ff;hson[u]=0; for(int i=h[u];i;i=e[i].next) { int v=e[i].v; if(v==ff)continue; DFS1(v,u); if(size[v]>size[hson[u]])hson[u]=v; size[u]+=size[v]; }}void DFS2(int u,int tp){ top[u]=tp;dfn[u]=++tim;line[tim]=u; if(hson[u])DFS2(hson[u],tp); for(int i=h[u];i;i=e[i].next) { int v=e[i].v; if(v==f[u]||v==hson[u])continue; DFS2(v,v); } low[u]=tim;}void Build(int now,int l,int r){ if(l==r){c[now].v=V[line[l]];return;} int mid=(l+r)>>1; Build(lson,l,mid);Build(rson,mid+1,r); c[now].v=c[lson].v+c[rson].v;}void pushdown(int now,int l,int r){ c[now].v+=1LL*(r-l+1)*c[now].lazy; c[lson].lazy+=c[now].lazy; c[rson].lazy+=c[now].lazy; c[now].lazy=0;}void update(int now,int l,int r,int al,int ar,int w){ if(l==al&&r==ar){c[now].lazy+=w;return;} int mid=(l+r)>>1; c[now].v+=1LL*(ar-al+1)*w; if(ar<=mid)update(lson,l,mid,al,ar,w); else if(al>mid)update(rson,mid+1,r,al,ar,w); else {update(lson,l,mid,al,mid,w);update(rson,mid+1,r,mid+1,ar,w);}}long long Query(int now,int l,int r,int al,int ar){ pushdown(now,l,r); if(l==al&&r==ar)return c[now].v; int mid=(l+r)>>1; if(ar<=mid)return Query(lson,l,mid,al,ar); if(al>mid)return Query(rson,mid+1,r,al,ar); return Query(lson,l,mid,al,mid)+Query(rson,mid+1,r,mid+1,ar);}long long Answer(int u){ int v=1,tp1=top[u],tp2=top[v]; long long ans=0; while(tp1!=tp2) { if(dep[tp1]<dep[tp2]) { swap(tp1,tp2); swap(u,v); } ans+=Query(1,1,N,dfn[tp1],dfn[u]); u=f[tp1];tp1=top[u]; } if(dep[u]<dep[v])swap(u,v); ans+=Query(1,1,N,dfn[v],dfn[u]); return ans;}int main(){ N=read();Q=read(); for(int i=1;i<=N;++i)V[i]=read(); for(int i=1;i<N;++i) { int u=read(),v=read(); Add(u,v);Add(v,u); } DFS1(1,0);DFS2(1,1); Build(1,1,N); while(Q--) { int kk=read(); if(kk==1) { int a=read(),b=read(); update(1,1,N,dfn[a],dfn[a],b); } if(kk==2) { int a=read(),b=read(); update(1,1,N,dfn[a],low[a],b); } if(kk==3) { int a=read(); printf("%lld\n",Answer(a)); } } return 0;}
阅读全文
0 0
- 【HAOI2015】树上操作(树链剖分)
- [HAOI2015]树上操作 -树链剖分
- bzoj 4034: [HAOI2015]树上操作 (树链剖分)
- 【BZOJ4034】树上操作(HAOI2015)-树链剖分
- 【bzoj4034】【HAOI2015】【树上操作】【树链剖分】
- bzoj4034 [HAOI2015]树上操作(树链剖分)
- 【树链剖分】bzoj4034: [HAOI2015]树上操作
- 【bzoj4034】[HAOI2015]树上操作(树链剖分+dfs序)
- bzoj4034: [HAOI2015]树上操作(树链剖分+线段树)
- 【BZOJ】4034 [HAOI2015]树上操作 树链剖分
- BZOJ 4034 [HAOI2015]树上操作 树链剖分
- bzoj 4034: [HAOI2015]树上操作 树链剖分
- BZOJ4034: [HAOI2015]树上操作(洛谷P3178)
- [HAOI2015]树上操作
- bzoj4034 [HAOI2015]树上操作
- 【bzoj4034】[HAOI2015]树上操作
- BZOJ4034: [HAOI2015]树上操作
- [bzoj4034][HAOI2015]树上操作
- 安卓8.0 新功能 新特性
- JavaFX设置Button圆角
- Irrelevant Elements UVA
- python初学1
- 猜数字游戏
- 【HAOI2015】树上操作(树链剖分)
- Codeforces 845B Luba And The Ticket (贪心)
- Java反射学习
- LeetCode刷题#595
- RTSP解析
- Quartz应用与集群原理分析
- HDU 3584 Cube(三位树状数组)
- 关于Home Lab的搭建——硬件选择篇(迷你主机)(一)
- JS能力测评经典题