HDU - 5692 Snacks 线段树+dfs序

题目链接:点击查看

百度科技园内有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;
}

猜你喜欢

转载自blog.csdn.net/mmk27_word/article/details/89319566