无向图 G = (Vn,En-1)构成一棵树,因此根节点O到树上各个节点的路径唯一,用线段树维护各个节点到O节点的权值之和(称为x的前缀和),每个节点的权值变化影响它和它子树的前缀和。
DFS先序遍历初始化各点的前缀和并储存在线段树中,对于每个节点x的变化,更新x和x子树的前缀和。(DFS先序遍历序列中属于同一子树的节点在连续区间中)
DFS序可以有效处理子树变化问题,把树上的统计问题转化为区间统计问题并用线段树和树状数组维护。---引申---树链剖分
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+5;
const long long INF=1e18;
struct Edge
{
int to,nxt;
}edge[MAX*2];
int head[MAX],tot;
int val[MAX];
long long val_[MAX];
long long a[MAX*4],lazy[MAX*4];
int l[MAX],r[MAX],nd[MAX],cnt;
void init()
{
tot=0;cnt=0;
memset(head,-1,sizeof(head));
}
void addedge(int x,int y)
{
edge[tot].to=y;
edge[tot].nxt=head[x];
head[x]=tot++;
edge[tot].to=x;
edge[tot].nxt=head[y];
head[y]=tot++;
}
void pushup(int rt)
{
a[rt]=max(a[rt*2],a[rt*2+1]);
}
void pushdown(int rt)
{
a[rt*2]+=lazy[rt];
a[rt*2+1]+=lazy[rt];
lazy[rt*2]+=lazy[rt];
lazy[rt*2+1]+=lazy[rt];
lazy[rt]=0;
}
void build(int rt,int l,int r)
{
lazy[rt]=0;
if(l==r)
{
a[rt]=val_[nd[l]];
return ;
}
int mid=(l+r)>>1;
build(rt*2,l,mid);
build(rt*2+1,mid+1,r);
pushup(rt);
}
void update(int rt,int l,int r,int L,int R,int val)
{
if (L<=l&&R>=r){a[rt]+=val;lazy[rt]+=val;return ;}
if (lazy[rt]) pushdown(rt);
int mid=(l+r)>>1;
if (L<=mid) update(rt*2,l,mid,L,R,val);
if (R>mid) update(rt*2+1,mid+1,r,L,R,val);
pushup(rt);
}
long long query(int rt,int l,int r,int L,int R)//区间查询
{
if(L<=l&&R>=r)return a[rt];
if(lazy[rt]) pushdown(rt);
int mid=(l+r)>>1;
long long sum=-INF;
if(L<=mid) sum=max(sum,query(rt*2,l,mid,L,R));
if(R>mid) sum=max(sum,query(rt*2+1,mid+1,r,L,R));
return sum;
}
void dfs(int x,int fa)
{
l[x]=++cnt;
nd[cnt]=x;
for(int i=head[x];i!=-1;i=edge[i].nxt)
{
int k=edge[i].to;
if(k!=fa)
{
val_[k]=val_[x]+val[k];
dfs(k,x);
}
}
r[x]=cnt;
}
int main()
{
int t,n,m,x,y;
scanf("%d",&t);
for(int tc=1;tc<=t;tc++)
{
init();
scanf("%d %d",&n,&m);
for(int i=0;i<n-1;i++)
{
scanf("%d %d",&x,&y);
addedge(x,y);
}
for(int i=0;i<n;i++) scanf("%d",&val[i]);
val_[0]=val[0];dfs(0,-1);
build(1,1,n);
printf("Case #%d:\n", tc);
while(m--)
{
scanf("%d",&x);
if(x==0)
{
scanf("%d %d",&x,&y);
update(1,1,n,l[x],r[x],y-val[x]);
val[x]=y;
}
else
{
scanf("%d",&x);
printf("%I64d\n",query(1,1,n,l[x],r[x]));
}
}
}
return 0;
}