DFS序2
给一棵有根树,这棵树由编号为1..N的N个结点组成。
根结点的编号为R 。每个结点都有一个权值,结点i的权值为Vi。
接下来有M组操作,操作分为两类:
1 a x,表示将结点a的子树上所有结点的权值增加x
2 a,表示求结点a的子树上所有结点的权值之和。
输入格式
第一行有三个整数N,M和 R。
第二行有N个整数,第i个整数表示Vi 。
在接下来的N-1行中,每行两个整数,表示一条边。
在接下来的M行中,每行一组操作。
1<=N,M<=1e6
-1e6<=vi,x<=1e6
输出格式
对于每组2 a操作,输出一个整数,表示「以结点a为根的子树」上所有结点的权值之和。
样例
输入
10 14 9
12 -6 -4 -3 12 8 9 6 6 2
8 2
2 10
8 6
2 7
7 1
6 3
10 9
2 4
10 5
1 4 -1
2 2
1 7 -1
2 10
1 10 5
2 1
1 7 -5
2 5
1 1 8
2 7
1 8 8
2 2
1 5 5
2 6
输出
21
33
16
17
27
76
30
#include <cstdio>
const int maxn = 1000005;
typedef long long LL;
int n, m, r;
int t[maxn], b[maxn];
// 线段树
LL tree[maxn << 2], mark[maxn << 2];
void build(int p, int l, int r){
if(l == r){
tree[p] = b[l];
return;
}
int mid = (l + r) / 2;
build(2 * p, l , mid);
build(2 * p + 1, mid + 1, r);
tree[p] = tree[2 * p] + tree[2 * p + 1];
}
void push_down(int p, int len){
tree[2 * p] += (len - len / 2) * mark[p];
tree[2 * p + 1] += (len / 2) * mark[p];
mark[2 * p] += mark[p];
mark[2 * p + 1] += mark[p];
mark[p] = 0;
}
void add(int p, LL x, int cl, int cr, int l, int r){
if(cr < l || cl > r) return;
if(l <= cl && cr <= r){
tree[p] += x * (cr - cl + 1);
mark[p] += x;
} else {
push_down(p, cr - cl + 1);
int mid = (cl + cr) / 2;
add(2 * p, x, cl, mid, l , r);
add(2 * p + 1, x, mid + 1, cr, l, r);
tree[p] = tree[2 * p] + tree[2 * p + 1];
}
}
LL query(int p, int cl, int cr, int l, int r){
if(cr < l || cl > r) return 0;
if(l <= cl && cr <= r) return tree[p];
push_down(p, cr - cl + 1);
int mid = (cl + cr) / 2;
return query(2 * p, cl, mid, l, r) + query(2*p + 1, mid + 1, cr, l, r);
}
// 链式前向星
struct Edge{
int to, next;
} edge[maxn << 1];
int cnt = 0;
int head[maxn];
void add_edge(int u, int v){
edge[++cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt;
}
// dfs序
int tim = 0, L[maxn], R[maxn];
void dfs(int p, int fa)
{
L[p] = ++tim;
b[tim] = t[p];
for(int e = head[p]; e; e = edge[e].next)
{
int &to = edge[e].to;
if(to != fa) dfs(to, p);
}
R[p] = tim;
}
int main(){
scanf("%d%d%d", &n, &m, &r);
for(int i=1; i <= n; i++){
scanf("%d", &t[i]);
}
for(int i=1, u, v; i < n; i++){
scanf("%d%d", &u, &v);
add_edge(u, v);
add_edge(v, u);
}
dfs(r, 0);
build(1, 1, n);
for(int i=1, op, a, x; i <= m; i++){
scanf("%d", &op);
if(op == 1){
scanf("%d%d", &a, &x);
add(1, x, 1, n, L[a], R[a]);
} else {
scanf("%d", &a);
printf("%lld\n", query(1, 1, n, L[a], R[a]));
}
}
return 0;
}

浙公网安备 33010602011771号