题目链接:点击查看
百度科技园内有n个零食机,零食机之间通过n−1条路相互连通。每个零食机都有一个值v,表示为小度熊提供零食的价值。
由于零食被频繁的消耗和补充,零食机的价值v
会时常发生变化。小度熊只能从编号为0的零食机出发,并且每个零食机至多经过一次。另外,小度熊会对某个零食机的零食有所偏爱,要求路线上必须有那个零食机。
为小度熊规划一个路线,使得路线上的价值总和最大。
Input
输入数据第一行是一个整数T(T≤10)
,表示有T组测试数据。
对于每组数据,包含两个整数n,m(1≤n,m≤100000),表示有n个零食机,m次操作。
接下来n−1行,每行两个整数x和y(0≤x,y<n),表示编号为x的零食机与编号为y的零食机相连。
接下来一行由n个数组成,表示从编号为0到编号为n−1的零食机的初始价值v(|v|<100000)。
接下来m行,有两种操作:0 x y,表示编号为x的零食机的价值变为y;1 x,表示询问从编号为0的零食机出发,必须经过编号为x
零食机的路线中,价值总和的最大值。
本题可能栈溢出,辛苦同学们提交语言选择c++,并在代码的第一行加上:
`#pragma comment(linker, "/STACK:1024000000,1024000000") `
Output
对于每组数据,首先输出一行”Case #?:”,在问号处应填入当前数据的组数,组数从1开始计算。
对于每次询问,输出从编号为0的零食机出发,必须经过编号为x
零食机的路线中,价值总和的最大值。
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
题解:因为要从节点1走一条经过x的路径,那么终点就只能是节点x这一分支的节点,考虑到从节点1走下来,若到y,那么y的父辈节点的权值都要加上,所以我们先跑一边dfs序,先把每一个节点的权值加到他的所以孩子上,求得时候,直接求到达x这一分支所有节点的最大值即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
struct node{
int l,r;
ll val,laz;
}tree[N<<2];
struct edge{
int to,nex;
}e[N*2];
int n,m;
int val[N];
int head[N],len;
int in[N],out[N],p[N],cnt;
void init()
{
len=cnt=0;
for(int i=1;i<=n;i++)
head[i]=-1;
}
void addedge(int x,int y)
{
e[len].to=y;
e[len].nex=head[x];
head[x]=len++;
}
void dfs(int u,int fa)
{
in[u]=++cnt;p[cnt]=u;
int to;
for(int i=head[u];~i;i=e[i].nex)
{
to=e[i].to;
if(to==fa)continue;
dfs(to,u);
}
out[u]=cnt;
}
void pushup(int cur)
{
tree[cur].val=max(tree[cur<<1].val,tree[cur<<1|1].val);
}
void pushdown(int cur)
{
if(tree[cur].laz)
{
tree[cur<<1].laz+=tree[cur].laz;
tree[cur<<1|1].laz+=tree[cur].laz;
tree[cur<<1].val+=tree[cur].laz;
tree[cur<<1|1].val+=tree[cur].laz;
tree[cur].laz=0;
}
}
void build(int l,int r,int cur)
{
tree[cur].l=l;
tree[cur].r=r;
tree[cur].val=0;
tree[cur].laz=0;
if(l==r)
{
return;
}
int mid=(r+l)>>1;
build(l,mid,cur<<1);
build(mid+1,r,cur<<1|1);
pushup(cur);
}
void update(int pl,int pr,int cur,ll val)
{
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
tree[cur].val+=val;
tree[cur].laz+=val;
return;
}
pushdown(cur);
if(pl<=tree[cur<<1].r) update(pl,pr,cur<<1,val);
if(pr>=tree[cur<<1|1].l)update(pl,pr,cur<<1|1,val);
pushup(cur);
}
ll query(int pl,int pr,int cur)
{
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
return tree[cur].val;
}
pushdown(cur);
ll res=-1e18;
if(pl<=tree[cur<<1].r) res=max(res,query(pl,pr,cur<<1));
if(pr>=tree[cur<<1|1].l) res=max(res,query(pl,pr,cur<<1|1));
return res;
}
int main()
{
int T,nn=1;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
init();
int x,y;
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
x++;y++;
addedge(x,y);
addedge(y,x);
}
dfs(1,0);
build(1,n,1);
for(int i=1;i<=n;i++)
{
scanf("%d",&val[i]);
update(in[i],out[i],1,val[i]);
}
int op;
printf("Case #%d:\n",nn++);
for(int i=1;i<=m;i++)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d",&x);x++;
printf("%lld\n",query(in[x],out[x],1));
}
else
{
scanf("%d%d",&x,&y);x++;
update(in[x],out[x],1,y-val[x]);
val[x]=y;
}
}
}
return 0;
}