# BZOJ 4034 树链剖分

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<stdio.h>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#include<set>
#include<time.h>
#include<cmath>
#include<sstream>
#include<assert.h>
using namespace std;
#define L(x) x<<1
#define R(x) x<<1|1
typedef long long int LL;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
const int MAXN = 100000+ 10;
struct Edge{
int to,next;
Edge(int _to = 0, int _next = 0) :to(_to), next(_next){};
}Edges[MAXN * 2];
Edges[tot].to = v;
}
int id[MAXN], endid[MAXN], son[MAXN], deep[MAXN], size[MAXN], fa[MAXN], reid[MAXN], top[MAXN];
void Init(){
tot = 0; cnt = 0;
memset(son, -1, sizeof(son));
}
void DFS1(int u, int p,int dep){
fa[u] = p; size[u] = 1; deep[u] = dep;
for (int i = head[u]; i != -1; i = Edges[i].next){
if (Edges[i].to != p){
DFS1(Edges[i].to, u,dep+1);
size[u] += size[Edges[i].to];
if (son[u] == -1 || size[Edges[i].to] > size[son[u]]){
son[u] = Edges[i].to;
}
}
}
}
void DFS2(int u, int tp){
id[u] = ++cnt; reid[id[u]] = u; top[u] = tp;
if (son[u] == -1){
endid[u] = cnt;
return;
}
DFS2(son[u], tp);
for (int i = head[u]; i != -1; i = Edges[i].next){
if (son[u] != Edges[i].to&&Edges[i].to != fa[u]){
DFS2(Edges[i].to, Edges[i].to);
}
}
endid[u] = cnt;
}
struct Node{
int st, ed;
LL sum, lazy;
}Seg[MAXN * 4];
void Build(int l, int r, int k){
Seg[k].st = l; Seg[k].ed = r; Seg[k].lazy = 0;
if (l == r){
Seg[k].sum = val[reid[l]];
return;
}
int mid = (l + r) / 2;
Build(l, mid, L(k)); Build(mid + 1, r, R(k));
Seg[k].sum = Seg[L(k)].sum + Seg[R(k)].sum;
}
void pushUp(int k){
Seg[k].sum = Seg[L(k)].sum + Seg[R(k)].sum;
}
void pushDown(int k){
if (Seg[k].lazy){
Seg[L(k)].sum += 1LL*Seg[k].lazy*(Seg[L(k)].ed - Seg[L(k)].st + 1);
Seg[L(k)].lazy += Seg[k].lazy;
Seg[R(k)].sum += 1LL*Seg[k].lazy*(Seg[R(k)].ed - Seg[R(k)].st + 1);
Seg[R(k)].lazy += Seg[k].lazy;
Seg[k].lazy = 0;
}
}
void Add(int l, int r, int k,int val){
if (Seg[k].st == l&&Seg[k].ed == r){
Seg[k].lazy += val;
Seg[k].sum += 1LL * val * (r - l + 1);
return;
}
pushDown(k);
if (r <= Seg[L(k)].ed){
}
else if (l >= Seg[R(k)].st){
}
else{
}
pushUp(k);
}
LL Query(int l, int r, int k){
if (Seg[k].st == l&&Seg[k].ed == r){
return Seg[k].sum;
}
pushDown(k);
LL sum = 0;
if (r <= Seg[L(k)].ed){
sum=Query(l, r, L(k));
}
else if (l >= Seg[R(k)].st){
sum=Query(l, r, R(k));
}
else{
sum=Query(l, Seg[L(k)].ed, L(k)) + Query(Seg[R(k)].st, r, R(k));
}
pushUp(k);
return sum;
}
LL Query(int x){
LL ans = 0;
while (top[x]!=1){
ans += Query(id[top[x]], id[x],1);
x = fa[top[x]];
}
ans += Query(1,id[x], 1);
return ans;
}
int main(){
//#ifdef kirito
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//#endif
//    int start = clock();
int n, m;
while (~scanf("%d%d",&n,&m)){
Init();
for (int i = 1; i <= n; i++){
scanf("%d", &val[i]);
}
for (int i = 1; i < n; i++){
int u, v;
scanf("%d%d", &u, &v);
}
DFS1(1, 1, 0); DFS2(1, 1);
Build(1, n, 1);
while (m--){
int ope, x, a;
scanf("%d", &ope);
switch (ope)
{
case 1:scanf("%d%d", &x, &a); Add(id[x],id[x] , 1, a); break;
case 2:scanf("%d%d", &x, &a); Add(id[x], endid[x], 1, a); break;
default: scanf("%d", &x);  printf("%lld\n", Query(x)); break;
}
}
}
//#ifdef LOCAL_TIME
//    cout << "[Finished in " << clock() - start << " ms]" << endl;
//#endif
return 0;
}

posted @ 2017-02-28 12:54  キリト  阅读(110)  评论(0编辑  收藏  举报