HDU-5692-Snacks(DFS序+线段树,单点修改,区间查询)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5692

Problem Description

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

中文题,题意很好懂,题目可以理解成:对于一棵树,修改一个点,或,查询那颗点一下的子树的的最大值,很容易想到线段树解决,学了一下DFS序,发现这道题是 问题1的变形,只不过换成取最大值,理解DFS序后就比较简单了;

注意,我这里没法用memset,因为用之后就直接70K+的内存空间,直接MLE,但改成手动赋值之后就只有13K+的内存空间,我也不太清楚,还有就是输入输出scanf,负责会TLE。。

ac:

#pragma comment(linker, "/STACK:1024000000,1024000000") 
 
#include<stdio.h>
#include<string.h>  
#include<math.h>  
#include<stdlib.h>

//#include<map>   
//#include<set>
#include<deque>  
#include<queue>  
#include<stack>  
#include<bitset> 
#include<string>  
#include<fstream>
#include<iostream>  
#include<algorithm>  
using namespace std;  
 
#define ll long long  
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b) 
#define clean(a,b) memset(a,b,sizeof(a))// 水印 
//std::ios::sync_with_stdio(false);
const int MAXN=1e5+5;
const ll INF=1e18;
const ll mod=1e9+7; 
struct node{
	int v,w,nxt;
	node(int _v=0,int _nxt=0):
	v(_v),nxt(_nxt){}
}edge[MAXN<<1];
int head[MAXN],ecnt;
ll tree[MAXN<<2],add[MAXN<<2],value[MAXN],dis[MAXN];
int L[MAXN],R[MAXN],arr[MAXN];
//x所对应在线段树左的节点,同理右,线段树上x对应的节点是多少arr[x]; 
int n,m,cnt;

void intt()
{
//	clean(L,0);
//	clean(R,0);
//	clean(dis,0);
//	clean(add,0);
//	clean(tree,0);
//	clean(value,0);
	clean(head,-1);	
//	memset(head,-1,sizeof(head));
	ecnt=0;
	cnt=0;//从0开始变成从1开始 
} 
void add_edge(int u,int v)
{	
	edge[ecnt]=node(v,head[u]);	
	head[u]=ecnt++;
}

void dfs(int u,int fa)
{
	L[u]=++cnt;
	arr[cnt]=u;
	for(int i=head[u];i+1;i=edge[i].nxt)
	{
		int v=edge[i].v;
		if(v==fa)
			continue;
		dis[v]=dis[u]+value[v];
		dfs(v,u);
	}
	R[u]=cnt;
}

void push_down(int rt)
{
	if(add[rt])
	{
		tree[rt<<1]+=add[rt];
		tree[rt<<1|1]+=add[rt];
		
		add[rt<<1]+=add[rt];
		add[rt<<1|1]+=add[rt];
		add[rt]=0;
	}
}

void build_tree(int l,int r,int rt)
{
	add[rt]=0;
	if(l==r)
	{
		tree[rt]=dis[arr[l]];
		return ;
	}
	int mid=(l+r)>>1;
	build_tree(l,mid,rt<<1);
	build_tree(mid+1,r,rt<<1|1);
	tree[rt]=max(tree[rt<<1],tree[rt<<1|1]);
}

void updata(int left,int right,int val,int l,int r,int rt)
{
	if(left<=l&&right>=r)//找到目标范围 
	{
		add[rt]+=val;
		tree[rt]+=val;
		return ;
	}
	//有一部分在范围外 
	push_down(rt);//向下推进 
	int mid=(l+r)>>1;
	if(left<=mid)
		updata(left,right,val,l,mid,rt<<1);
	if(right>mid)
		updata(left,right,val,mid+1,r,rt<<1|1);
	tree[rt]=max(tree[rt<<1],tree[rt<<1|1]);
}

ll Query(int left,int right,int l,int r,int rt)
{
	if(left<=l&&right>=r)
		return tree[rt];
	push_down(rt);
	int mid=(l+r)>>1;
	ll ans=-INF;
	if(left<=mid)
		ans=max(ans,Query(left,right,l,mid,rt<<1));
	if(right>mid)
		ans=max(ans,Query(left,right,mid+1,r,rt<<1|1));
	return ans;
}

int main()
{
	//std::ios::sync_with_stdio(false);
    int T,Case=1;
    scanf("%d",&T);
    while(T--)
    {
    	//cout<<"T: "<<T<<endl;
    	intt();
    	scanf("%d%d",&n,&m);
    	int a,b;
    	for(int i=1;i<n;++i)//建边 
    	{
    		scanf("%d%d",&a,&b);
    		add_edge(a,b);
    		add_edge(b,a);
		}
		for(int i=0;i<n;++i)//读入权值 
			scanf("%lld",&value[i]);//cin>>value[i];
		dis[0]=value[0];
		dfs(0,-1);
		build_tree(1,n,1);
		bool oper;
		cout<<"Case #"<<Case++<<":"<<endl;
		for(int i=1;i<=m;++i)
		{
			scanf("%d",&oper);
			if(oper)//找 
			{
				scanf("%d",&a);
				cout<<Query(L[a],R[a],1,n,1)<<endl;
			}
			else//换 
			{
				scanf("%d%d",&a,&b);
				updata(L[a],R[a],b-value[a],1,n,1);
				value[a]=b;
			}
		}
	}
}

/*
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
*/

猜你喜欢

转载自blog.csdn.net/qq_40482358/article/details/82956737