思路:题目要求必须从0号结点经过x号结点,那么其实就是求x号结点的子树到0号结点的最大距离,那么可以先DFS一遍把DFS序弄出来,顺便预处理每一个结点到0号结点的距离,然后建线段树,维护结点到0号结点的距离就可以了
#pragma comment(linker, "/STACK:1024000000,1024000000") `
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
const int maxn = 100000+7;
#define inf 1LL<<58
LL dis[maxn],a[maxn];
LL sum[maxn<<2],lazy[maxn<<2];
vector<int>e[maxn];
int n,m,in[maxn],out[maxn],vis[maxn],tot;
void push_up(int i)
{
sum[i]=max(sum[i<<1],sum[i<<1|1]);
}
void push_down(int i)
{
if(lazy[i])
{
lazy[i<<1]+=lazy[i];
lazy[i<<1|1]+=lazy[i];
sum[i<<1]+=lazy[i];
sum[i<<1|1]+=lazy[i];
lazy[i]=0;
}
}
void build(int i,int l,int r)
{
lazy[i]=0;
if(l==r)
{
sum[i]=dis[vis[l]];
return;
}
int mid = (l+r)>>1;
build(lson);
build(rson);
push_up(i);
}
void update(int ql,int qr,int v,int i,int l,int r)
{
if(ql<=l&&qr>=r)
{
lazy[i]+=v;
sum[i]+=v;
return;
}
push_down(i);
int mid = (l+r)>>1;
if(ql<=mid)
update(ql,qr,v,lson);
if(qr>mid)
update(ql,qr,v,rson);
push_up(i);
}
LL query(int ql,int qr,int i,int l,int r)
{
if(ql<=l&&qr>=r)
return sum[i];
push_down(i);
int mid = (l+r)>>1;
LL ans = -inf;
if(ql<=mid)
ans = max(ans,query(ql,qr,lson));
if(qr>mid)
ans = max(ans,query(ql,qr,rson));
return ans;
}
void dfs(int u,int fa)
{
in[u]=++tot;
vis[tot]=u;
for(int i = 0;i<e[u].size();i++)
{
int v = e[u][i];
if(v==fa)continue;
dis[v] = dis[u]+a[v];
dfs(v,u);
// dis[v]=dis[u]+a[v];
}
out[u]=tot;
}
int main()
{
int T,cas=1;
scanf("%d",&T);
while(T--)
{
printf("Case #%d:\n",cas++);
scanf("%d%d",&n,&m);
for(int i = 0;i<=n;i++)
e[i].clear();
tot=0;
for(int i = 0;i<n-1;i++)
{
int u,v;
scanf("%d%d",&u,&v);
u++,v++;
e[u].push_back(v);
e[v].push_back(u);
}
for(int i =1;i<=n;i++)
scanf("%lld",&a[i]);
dis[1]=a[1];
dfs(1,-1);
build(1,1,tot);
for(int i = 1;i<=m;i++)
{
int op;
scanf("%d",&op);
if(op==0)
{
int u,v;
scanf("%d%d",&u,&v);
u++;
update(in[u],out[u],v-a[u],1,1,tot);
a[u]=v;
}
else
{
int u;
scanf("%d",&u);
u++;
printf("%lld\n",query(in[u],out[u],1,1,tot));
}
}
}
}