题目分析
这道题主要是建树的时候不好想,自己也没有做过这种类似的题目,因此不会。不过很容易理解,如果你学过LCA的离线算法,那么对这道题的理解可能会更好。总结起来只有关键的一句话,dfs序的每个子树的序列号是连续的,我们就根据这个建立线段树就行了。
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5+100;
#define LL long long
#define mid (L+R)/2
#define lson o<<1, L, mid
#define rson o<<1|1, mid+1, R
const LL INF = 0x3f3f3f3f3f3f3f;
struct Edge{
int to, next;
}e[maxn<<1];
int head[maxn], tot, dfs_clock;
LL sum[maxn<<2], lazy[maxn<<2], val[maxn];
int cost[maxn], le[maxn], ri[maxn];
void dfs(int u, int fa, LL vv){
le[u] = ++dfs_clock;
for(int i = head[u]; i != -1; i = e[i].next){
int v = e[i].to;
if(v == fa) continue;
dfs(v, u, vv+cost[v]);
}
ri[u] = dfs_clock;
val[le[u]] = vv;
}
void pushdown(int o){
if(lazy[o]){
lazy[o<<1] += lazy[o];
lazy[o<<1|1] += lazy[o];
sum[o<<1] += lazy[o];
sum[o<<1|1] += lazy[o];
lazy[o] = 0;
}
}
void build(int o, int L, int R){
if(L == R){
sum[o] = val[L];
return ;
}
build(lson);
build(rson);
sum[o] = max(sum[o<<1], sum[o<<1|1]);
}
void update(int o, int L, int R, int l, int r, LL v){
if(l <= L && R <= r){
sum[o] += v;
lazy[o] += v;
return ;
}
pushdown(o);
if(l <= mid) update(lson, l, r, v);
if(r > mid) update(rson, l, r, v);
sum[o] = max(sum[o<<1], sum[o<<1|1]);
}
LL query(int o, int L, int R, int l, int r){
if(l <= L && R <= r) return sum[o];
pushdown(o);
LL ans = -INF;
if(l <= mid) ans = max(ans, query(lson, l, r));
if(r > mid) ans = max(ans, query(rson, l, r));
return ans;
}
void addedge(int from, int to){
e[tot].to = to;
e[tot].next = head[from];
head[from] = tot++;
}
void init(){
memset(lazy, 0, sizeof(lazy));
memset(head, -1, sizeof(head));
tot = dfs_clock = 0;
}
int main(){
int T, n, m, x, y, op;
scanf("%d", &T);
for(int kase = 1; kase <= T; kase++){
init();
scanf("%d%d", &n, &m);
for(int i = 1; i < n; i++){
scanf("%d%d", &x, &y);
x++, y++;
addedge(x, y);
addedge(y, x);
}
for(int i = 1; i <= n; i++) scanf("%d", &cost[i]);
dfs(1, 0, (LL)cost[1]);
build(1, 1, n);
printf("Case #%d:\n", kase);
while(m--){
scanf("%d", &op);
if(op){
scanf("%d", &x); x++;
printf("%I64d\n", query(1, 1, n, le[x], ri[x]));
}
else{
scanf("%d%d", &x, &y); x++;
update(1, 1, n, le[x], ri[x], y - cost[x]);
cost[x] = y;
}
}
}
return 0;
}