给一棵有根树,这棵树由编号为1..N的N个结点组成。根结点的编号为R。
每个结点都有一个权值,结点i的权值为vi 。
接下来有M组操作,操作分为两类:
1 a x,表示将结点a的权值增加x;
2 a,表示求结点a的子树上所有结点的权值之和。
输入格式
第一行有三个整数N,M和R。
第二行有N个整数,第i个整数表示vi 。
在接下来的N-1行中,每行两个整数,表示一条边。
在接下来的M行中,每行一组操作。
输出格式
对于每组2 a操作,输出一个整数,表示「以结点a为根的子树」上所有结点的权值之和。
样例
样例输入 1
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
样例输出 1
21
34
12
12
23
31
4
1<=N,M<=10^6,1<=R<=N
-10^6<=vi,x<=10^6
#include <bits/stdc++.h> using namespace std; const int maxn = 1e6 + 6; typedef long long ll; ll c[maxn], in[maxn], out[maxn], tot, d[maxn], head[maxn], cnt, n, m, r; struct node { int to, nxt; } e[maxn << 1]; void addedge(int u, int v) { e[++tot] = { v, head[u] }; head[u] = tot; } void dfs(int u) { in[u] = ++cnt; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (in[v]) continue; dfs(v); } out[u] = cnt; } ll lowbit(int x) { return x & -x; } void add(int u, int x) { while (u <= n) { c[u] += x; u += lowbit(u); } } ll query(int u) { ll ret = 0; while (u > 0) { ret += c[u]; u -= lowbit(u); } return ret; } int main() { cin >> n >> m >> r; for (int i = 1; i <= n; ++i) cin >> d[i]; for (int i = 1, a, b; i < n; ++i) { cin >> a >> b; addedge(a, b), addedge(b, a); } dfs(r); for (int i = 1; i <= n; ++i) //最始权值 add(in[i], d[i]); for (int i = 1, op, a, x; i <= m; ++i) { cin >> op >> a; if (op == 2) { cout << query(out[a]) - query(in[a] - 1) << endl; } else { cin >> x; add(in[a], x); } } }