题目描述
这是一道模板题。
给一棵有根树,这棵树由编号为1...N的N个结点组成。根结点的编号为R。每个结点都有一个权值,结点i的权值为Vi 。
接下来有 组操作,操作分为两类:
- 1 a x,表示将结点a 的权值增加 x;
- 2 a,表示求结点a的子树上所有结点的权值之和。
输入
第一行有三个整数N,M和R 。
第二行有 N个整数,第i 个整数表示Vi。
在接下来的N-1 行中,每行两个整数,表示一条边。
在接下来的M 行中,每行一组操作。
输出
对于每组 2 a 操作,输出一个整数,表示「以结点 为根的子树」上所有结点的权值之和。
样例输入 Copy
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
样例输出 Copy
21
34
12
12
23
31
4
提示
N,M<=1e6,R<=N,-1e6<=Vi ,x<=1e6
来源/分类
思路:按dfs遍历序重新给节点标号,每个节点的子树节点就能用区间表示 ,接下来就可以用线段树,树状数组,zkw线段树,解决单点更新区间求和的问题
线段树代码:
//Time:1372 ms
//Memory:71392 kb
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int N=1000005;