题解:是个好题,对于经过某一点的最大值,可以将某一点作为根,他的子树中到0的最大值即为解。那么这样,可以用dfs跑出一个序,即当前点到0的值,每个点维护一个L,R区间,那么这个区间的点就是它的子树。对于单点更新一个值,那么就变成区间更新,更新这个点L,R区间所以点的值,对于查询,就是L,R区间中的最大值
(注意LL和INF)
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <cstring>
#include <vector>
#include <set>
#include <cmath>
#define LL long long
#define INF 1e18
#define mod 1000000007
const int maxn = 100000 + 5;
using namespace std;
int n,m,cnt,idx;
LL a[maxn];
int head[maxn];
int L[maxn];
int R[maxn];
LL dis[maxn];
LL lazy[maxn*4];
LL ans[maxn*4];
int ver[maxn];//dfs序数组的下标
struct Edge{
int to;
int next;
}edge[maxn*2];
void init(){
cnt = idx = 0;
memset(head, -1, sizeof(head));
memset(lazy, 0, sizeof(lazy));
}
void addedge(int u, int v){
edge[cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt++;
}
void dfs(int cur, int fa){
L[cur] = ++idx;
ver[idx] = cur;
for(int i=head[cur]; i!=-1; i=edge[i].next){
int v = edge[i].to;
if(v != fa) {
dis[v] = dis[cur] + a[v];
dfs(v,cur);
}
}
R[cur] = idx;
}
void pushdown(int o){
if(lazy[o]){
ans[o*2] += lazy[o];
ans[o*2+1] += lazy[o];
lazy[o*2] += lazy[o];
lazy[o*2+1] += lazy[o];
lazy[o] = 0;
}
return;
}
void build(int l, int r, int o){
if(l == r){
ans[o] = dis[ver[l]];
return;
}
int m = (l+r)/2;
build(l,m,o*2);
build(m+1,r,o*2+1);
ans[o] = max(ans[o*2],ans[o*2+1]);
return;
}
void update(int val, int ql, int qr, int l, int r, int o){
if(ql <= l && qr >= r){
lazy[o] += val;
ans[o] += val;
return;
}
int m = (l+r)/2;
pushdown(o);
if(m >= ql)
update(val,ql,qr,l,m,o*2);
if(m < qr)
update(val,ql,qr,m+1,r,o*2+1);
ans[o] = max(ans[o*2],ans[o*2+1]);
}
LL query(int ql, int qr, int l, int r, int o){
if(ql <= l && qr >= r)
return ans[o];
int m = (l+r)/2;
pushdown(o);
LL ANS = -INF;
if(m >= ql)
ANS = max(ANS, query(ql,qr,l,m,o*2));
if(m < qr)
ANS = max(ANS, query(ql,qr,m+1,r,o*2+1));
return ANS;
}
int main(){
int T, kases = 1;
scanf("%d",&T);
while(T--){
init();
scanf("%d%d",&n,&m);
for(int i=0; i<n-1; i++){
int u,v;
scanf("%d%d",&u,&v);
addedge(u, v);
addedge(v, u);
}
for(int i=0; i<n; i++)
scanf("%lld",&a[i]);
dis[0] = a[0];
dfs(0,-1);//跑出一个dfs序数组
// for(int i=1; i<=n; i++)
// cout << ver[i] << " ";
// cout << endl;
// for(int i=0; i<n; i++){
// cout << "i : " << i << " L = " << L[i] << " R = " << R[i] << endl;
// }
build(1,n,1);
printf("Case #%d:\n",kases++);
while(m--){
int op,x,y;
scanf("%d",&op);
if(op == 1){
scanf("%d",&x);
printf("%lld\n",query(L[x],R[x],1,n,1));
}
else{
scanf("%d%d",&x,&y);
update(y-a[x],L[x],R[x],1,n,1);
a[x] = y;
}
}
}
return 0;
}