dfs序+线段树。
用线段树维护从根节点到每一个节点的距离。
修改操作就是x子树对应区间加上一个值。
查询操作就是查询x子树对应区间的最大值。
#include<cstdio> #include <iostream> #include<cstring> #include<cmath> #include<vector> #include<queue> #include<algorithm> using namespace std; long long INF=10000000+10; const int maxn=100000+10; int n,m; vector<int>Tree[maxn]; long long val[maxn]; int L[maxn],R[maxn],tot; bool flag[maxn]; struct SegTree { long long MAX,lazy; }s[8*maxn]; long long ans; void dfs(int x) { L[x]=++tot; flag[x]=1; for(int i=0;i<Tree[x].size();i++) if(flag[Tree[x][i]]==0) dfs(Tree[x][i]); R[x]=++tot; } void init() { INF=10000000+10; INF=INF*INF; tot=0; memset(flag,0,sizeof flag); for(int i=1;i<=n;i++) Tree[i].clear(); } void build(int l,int r,int rt) { s[rt].MAX=s[rt].lazy=0; if(l==r) return; int m=(l+r)/2; build(l,m,2*rt); build(m+1,r,2*rt+1); } void pushUp(int rt) { s[rt].MAX=max(s[2*rt].MAX,s[2*rt+1].MAX); } void pushDown(int rt) { if(s[rt].lazy!=0) { s[2*rt].MAX+=s[rt].lazy; s[2*rt+1].MAX+=s[rt].lazy; s[2*rt].lazy+=s[rt].lazy; s[2*rt+1].lazy+=s[rt].lazy; s[rt].lazy=0; } } void update(int L,int R,int l,int r,int rt,long long val) { if(L<=l&&r<=R) { s[rt].MAX+=val;s[rt].lazy+=val; return; } int m=(l+r)/2; pushDown(rt); if(L<=m) update(L,R,l,m,2*rt,val); if(R>m) update(L,R,m+1,r,2*rt+1,val); pushUp(rt); } void quary(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R) { ans=max(ans,s[rt].MAX); return; } int m=(l+r)/2; pushDown(rt); if(L<=m) quary(L,R,l,m,2*rt); if(R>m) quary(L,R,m+1,r,2*rt+1); pushUp(rt); } int main() { int T; scanf("%d",&T); int Case=1; while(T--) { scanf("%d%d",&n,&m);init(); for(int i=1;i<=n-1;i++) { int u,v; scanf("%d%d",&u,&v); u++; v++; Tree[u].push_back(v); Tree[v].push_back(u); } for(int i=1;i<=n;i++) scanf("%lld",&val[i]); dfs(1); build(1,tot,1); for(int i=1;i<=n;i++) update(L[i],R[i],1,tot,1,val[i]); printf("Case #%d: ",Case++); for(int i=1;i<=m;i++) { int op; scanf("%d",&op); if(op==0) { int x; long long y; scanf("%d%lld",&x,&y); x++; update(L[x],R[x],1,tot,1,y-val[x]); val[x]=y; } else { int x; scanf("%d",&x); ans=-INF; x++; quary(L[x],R[x],1,tot,1); printf("%lld ",ans); } } } return 0; }