您的位置:首页 > 理论基础 > 数据结构算法

数据结构(树链剖分):BZOJ 4034: [HAOI2015]T2

2016-03-30 14:18 507 查看

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 。

  

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
using namespace std;
const int maxn=100010;
int cnt,fir[maxn],to[maxn<<1],nxt[maxn<<1],n,m;
void addedge(int a,int b){
nxt[++cnt]=fir[a];to[cnt]=b;fir[a]=cnt;
}
long long key[maxn],tr[maxn<<2],add[maxn<<2];
int ID[maxn],fa[maxn],top[maxn],end[maxn],sz[maxn],son[maxn];
void Push_up(int x){
tr[x]=tr[x<<1]+tr[x<<1|1];
}
void Add(int x,int l,int r,long long d){
tr[x]+=(r-l+1)*d;
add[x]+=d;
}
void Push_down(int x,int l,int r){
if(add[x]){
int mid=(l+r)>>1;
Add(x<<1,l,mid,add[x]);
Add(x<<1|1,mid+1,r,add[x]);
add[x]=0;
}
}
void Updata(int node,int l,int r,int a,int b,long long d){
if(l>=a&&r<=b){
Add(node,l,r,d);
return;
}
Push_down(node,l,r);
int mid=(l+r)>>1;
if(mid>=a)Updata(node<<1,l,mid,a,b,d);
if(mid<b) Updata(node<<1|1,mid+1,r,a,b,d);
Push_up(node);
}
long long Query(int node,int l,int r,int a,int b){
if(l>=a&&r<=b)return tr[node];
Push_down(node,l,r);
int mid=(l+r)>>1;
long long ret=0;
if(mid>=a)ret=Query(node<<1,l,mid,a,b);
if(mid<b) ret+=Query(node<<1|1,mid+1,r,a,b);
return ret;
}
void DFS(int x){
sz[x]=1;
for(int i=fir[x];i;i=nxt[i]){
if(to[i]==fa[x])continue;
fa[to[i]]=x;
DFS(to[i]);
sz[x]+=sz[to[i]];
son[x]=sz[son[x]]<sz[to[i]]?to[i]:son[x];
}
}
long long Solve(int y){
long long ret=0;
while(y){
ret+=Query(1,1,n,ID[top[y]],ID[y]);
y=fa[top[y]];
}
return ret;
}
int cont;
void DFS2(int x,int tp){
ID[x]=++cont;top[x]=tp;
if(son[x])DFS2(son[x],tp);
for(int i=fir[x];i;i=nxt[i])
if(to[i]!=fa[x]&&to[i]!=son[x])
DFS2(to[i],to[i]);
end[x]=cont;
}
int main(){
freopen("t2.in","r",stdin);
freopen("t2.out","w",stdout);
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%lld",&key[i]);

for(int i=1,a,b;i<n;i++){
scanf("%d %d",&a,&b);
addedge(a,b);
addedge(b,a);
}

DFS(1);
DFS2(1,1);

for(int i=1;i<=n;i++)
Updata(1,1,n,ID[i],ID[i],key[i]);
int op,x,a;
while(m--){
scanf("%d",&op);
if(op==1){
scanf("%d%d",&x,&a);
Updata(1,1,n,ID[x],ID[x],a);
}
else if(op==2){
scanf("%d%d",&x,&a);
Updata(1,1,n,ID[x],end[x],a);
}
else{
scanf("%d",&x);
printf("%lld\n",Solve(x));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: