0%

找路径

给定一棵含有n个节点的树,每个点上都有一个权值,有m个操作属于以下两种之一:

0 x y: 把x点的权值改为y

1 x: 询问从0出发,经过x的路径,最大和是多少?

输入描述:

第一行两个整数n和m
接下来n-1,每行两个整数,表示树上的一条边。
接下一行n个整数,表示每个节点上的权值v。
接下来m行,每行表示一个询问。

输出描述:

对于每个询问,输出一个整数

示例1
输入

6 5
0 1
1 2
0 3
3 4
5 3
7 -5 100 20 -5 -7
1 1
1 3
0 2 -1
1 1
1 5

输出

102
27
2
20

zhaolujing.cppview raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <iostream>
#include <vector>
using namespace std;

const int N = 100010;
typedef long long LL;
int n,m;

vector<int>edges[N];
int val[N]; // number on this node
int Lid[N], Rid[N], tot;
int Line[N]; //map from dfs_id to original id
LL dis[N]; // accumulated number from root till this node

void dfs(int x, int f, LL d){
Lid[x] = ++tot; dis[x] = d; Line[tot] = x;
for(int i=0;i<edges[x].size();i++){
int j = edges[x][i];
if(j==f) continue;
dfs(j, x, d + val[j]);
}
Rid[x] = tot;
}

struct Node{
int L, R;
LL mx, add;
}tree[N<<2];


void up(int p){
tree[p].mx = max(tree[p<<1].mx, tree[p<<1|1].mx);
}

void build(int L, int R, int p){
tree[p].L = L, tree[p].R = R;
tree[p].add = 0;
if(L==R){
tree[p].mx = dis[Line[L]];
return;
}
int mid = (L + R )>>1;
build(L, mid, p<<1);
build(mid+1, R, p<<1|1);
up(p);
}

void down(int p){
LL &t = tree[p].add;
if(t==0) return;
tree[p<<1].add += t;
tree[p<<1].mx += t;
tree[p<<1|1].add += t;
tree[p<<1|1].mx += t;
t = 0;
}

void update(int L, int R, int x, int p){
if(tree[p].L == L && tree[p].R ==R){
tree[p].add += x;
tree[p].mx += x;
return;
}
down(p);
int mid = (tree[p].L + tree[p].R )>>1;
if(R<=mid) update(L, R, x, p<<1);
else if(L>mid) update(L, R, x, p<<1|1);
else{
update(L, mid, x, p<<1);
update(mid+1, R, x, p<<1|1);

}
up(p);
}

LL query(int L, int R, int p){
if(tree[p].L == L && tree[p].R ==R ){
return tree[p].mx;
}
down(p);
int mid = (tree[p].L + tree[p].R) >>1;
if(R<=mid) return query(L,R, p<<1);
else if(L>mid) return query(L, R, p<<1|1);
else{
return max(query(L, mid, p<<1), query(mid+1, R, p<<1|1));
}
}

int main(){
scanf("%d%d", &n, &m);
int a, b;
for(int i=0;i<n;i++) edges[i].clear();
for(int i=1;i<n;i++){
scanf("%d%d", &a, &b);
edges[a].push_back(b);
edges[b].push_back(a);
}

for(int i=0;i<n;i++){
scanf("%d", &val[i]);
}
// dfs order
dfs(0, -1, val[0]);
build(1, tot, 1);
int c;
while(m--){
scanf("%d%d", &a, &b);
if(a==0){
scanf("%d", &c);
update(Lid[b], Rid[b], c-val[b], 1); // segment tree supports dfs_id manipulation
val[b] = c; // original id
}else{
printf("%d\n", query(Lid[b], Rid[b], 1));
}
}
return 0;
}