Problem Description
百度科技园内有个零食机,零食机之间通过条路相互连通。每个零食机都有一个值,表示为小度熊提供零食的价值。
由于零食被频繁的消耗和补充,零食机的价值会时常发生变化。小度熊只能从编号为0的零食机出发,并且每个零食机至多经过一次。另外,小度熊会对某个零食机的零食有所偏爱,要求路线上必须有那个零食机。
为小度熊规划一个路线,使得路线上的价值总和最大。
Input
输入数据第一行是一个整数,表示有组测试数据。
对于每组数据,包含两个整数,表示有个零食机,次操作。
接下来行,每行两个整数和,表示编号为的零食机与编号为的零食机相连。
接下来一行由个数组成,表示从编号为0到编号为的零食机的初始价值。
接下来行,有两种操作:,表示编号为的零食机的价值变为;,表示询问从编号为0的零食机出发,必须经过编号为零食机的路线中,价值总和的最大值。
本题可能栈溢出,辛苦同学们提交语言选择c++,并在代码的第一行加上:
`#pragma comment(linker, "/STACK:1024000000,1024000000") `
Output
对于每组数据,首先输出一行”Case #?:”,在问号处应填入当前数据的组数,组数从1开始计算。
对于每次询问,输出从编号为0的零食机出发,必须经过编号为零食机的路线中,价值总和的最大值。
Sample Input
1
6 5
0 1
1 2
0 3
3 4
5 3
7 -5 100 20 -5 -7
1 1
1 3
0 2 -1
1 1
1 5
Sample Output
Case #1:
102
27
2
20
思路:求经过x点到0点的最长路径 就直接用每个点到0点的距离建一颗线段树 维护最大值就可以 因为还要经过x点 就需要跑一边DFS序 l[x],r[x]就表示x子树的区间范围 x的子树上的点一定经过x 所以只需求l[x]~r[x]的区间最大值就是答案 修改操作就是线段树的区间修改
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <vector>
#define ll long long
#define inf 0x3f3f3f3f3f3f
using namespace std;
int L[100005], R[100005],tot;
ll Max[400005],lazy[400005],vv[100005];
int v[100005];
vector <int> Map[100005];
void dfs(int x,int fa,ll value)
{
L[x]=++tot;
vv[tot]=value;
for(int i=0;i<Map[x].size();i++)
{
if(Map[x][i]==fa)
{
continue;
}
dfs(Map[x][i],x,value+v[Map[x][i]]);
}
R[x]=tot;
}
void build(int l,int r,int rt)
{
lazy[rt]=0;
if(l==r)
{
Max[rt]=vv[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
}
void update(int l,int r,int L,int R,int x,int rt)
{
if(L<=l&&R>=r)
{
Max[rt]+=x;
lazy[rt]+=x;
return;
}
int mid=(l+r)>>1;
if(lazy[rt])
{
Max[rt<<1]+=lazy[rt];
Max[rt<<1|1]+=lazy[rt];
lazy[rt<<1]+=lazy[rt];
lazy[rt<<1|1]+=lazy[rt];
lazy[rt]=0;
}
if(L<=mid)
{
update(l,mid,L,R,x,rt<<1);
}
if(R>mid)
{
update(mid+1,r,L,R,x,rt<<1|1);
}
Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
}
ll query(int l,int r,int L,int R,int rt)
{
if(L<=l&&R>=r)
{
return Max[rt];
}
int mid=(l+r)>>1;
if(lazy[rt])
{
Max[rt<<1]+=lazy[rt];
Max[rt<<1|1]+=lazy[rt];
lazy[rt<<1]+=lazy[rt];
lazy[rt<<1|1]+=lazy[rt];
lazy[rt]=0;
}
ll ans=-inf;
if(L<=mid)
{
ans=max(ans,query(l,mid,L,R,rt<<1));
}
if(R>mid)
{
ans=max(ans,query(mid+1,r,L,R,rt<<1|1));
}
return ans;
}
signed main()
{
int T,cas=0;
scanf("%d",&T);
while(T--)
{
tot=-1;
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
{
Map[i].clear();
}
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
Map[u].push_back(v);
Map[v].push_back(u);
}
for(int i=0;i<n;i++)
{
scanf("%d",&v[i]);
}
dfs(0,-1,v[0]);
build(0,n-1,1);
printf("Case #%d:\n",++cas);
while(m--)
{
int x;
scanf("%d",&x);
if (x==0)
{
int y,z;
scanf("%d%d",&y,&z);
update(0,n-1,L[y],R[y],z-v[y],1);
v[y]=z;
}
else
{
int y;
scanf("%d",&y);
printf("%lld\n",query(0,n-1,L[y],R[y],1));
}
}
}
return 0;
}