# bzoj 4034: [HAOI2015]树上操作 （树剖+线段树 子树操作）

## 4034: [HAOI2015]树上操作

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 6779  Solved: 2275
[Submit][Status][Discuss]

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

6
9
13

## HINT

对于 100% 的数据， N,M<=100000 ，且所有输入数据的绝对值都不会超过 10^6 。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid ll m = (l + r) >> 1
const ll M = 2e5+10;
struct node{
ll to,next;
}e[M];
ll n,m,cnt1,cnt,a[M];
}

void dfs1(ll u,ll faz,ll deep){
dep[u] = deep;
fa[u] = faz;
siz[u] = 1;
ll v = e[i].to;
if(v != fa[u]){
dfs1(v,u,deep+1);
siz[u] += siz[v];
if(son[u] == -1||siz[v] > siz[son[u]])
son[u] = v;
}
}
}

void dfs2(ll u,ll t){
top[u] = t;
mx[u] = cnt;
tid[u] = cnt;
rk[cnt] = u;
cnt++;
if(son[u] == -1) return;
dfs2(son[u],t),mx[u] = max(mx[u],mx[son[u]]);
for(ll i = head[u];i;i = e[i].next){
ll v = e[i].to;
if(v != son[u]&&v != fa[u])
dfs2(v,v),mx[u]=max(mx[u],mx[v]);
}
}

void pushup(ll rt){
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}

void pushdown(ll l,ll r,ll rt){
if(lazy[rt]){
mid;
sum[rt<<1] += lazy[rt]*(m-l+1);
sum[rt<<1|1] += lazy[rt]*(r - m);
lazy[rt<<1] += lazy[rt];
lazy[rt<<1|1] += lazy[rt];
lazy[rt] = 0;
}
}

void build(ll l,ll r,ll rt){
lazy[rt] = 0;
if(l == r){
sum[rt] = a[rk[l]];
return ;
}
mid;
build(lson);
build(rson);
pushup(rt);
}

void update(ll L,ll R,ll c,ll l,ll r,ll rt){
if(L <= l&&R >= r){
sum[rt] += c*(r-l+1);
lazy[rt]+=c;
return ;
}
pushdown(l,r,rt);
mid;
if(L <= m) update(L,R,c,lson);
if(R > m) update(L,R,c,rson);
pushup(rt);
}

ll query(ll L,ll R,ll l,ll r,ll rt){
if(L <= l&&R >= r){
return sum[rt];
}
pushdown(l,r,rt);
mid;
ll ret = 0;
if(L <= m) ret += query(L,R,lson);
if(R > m) ret += query(L,R,rson);
return ret;
}

ll ans = 0;
ll fx = top[x],fy = top[y];
while(fx != fy){
if(dep[fx] < dep[fy]) swap(x,y),swap(fx,fy);
ans += query(tid[fx],tid[x],1,n,1);
x = fa[fx];fx=top[x];
}
if(dep[x] > dep[y]) swap(x,y);
ans += query(tid[x],tid[y],1,n,1);
return ans;
}

int main()
{
ll u,v,x,y,z;
scanf("%lld%lld",&n,&m);
cnt1 = 0;cnt = 1;
memset(son,-1,sizeof(son));
for(ll i = 1;i <= n;i ++){
scanf("%lld",&a[i]);
}
for(ll i = 0;i < n-1;i++){
scanf("%lld%lld",&u,&v);
}
dfs1(1,0,1);dfs2(1,1),build(1,n,1);
while(m--){
scanf("%lld%lld",&x,&y);
if(x==1){
scanf("%lld",&z);
update(tid[y],tid[y],z,1,n,1);
}
else if(x == 2){
scanf("%lld",&z);
update(tid[y],mx[y],z,1,n,1);
}
else{
}