HDU5692 Snacks

我太难了

\(HDU\) 卡前向星 , \(POJ\) 卡 \(vector\)

我真的是服了

Description

link

给定一棵树,要求支持如下操作:

\(1.\) 单点修改权值

\(2.\) 查询经过某点的权值和最大的链

Solution

其实挺简单的吧,就是先一遍 \(dfs\) 把树上的权值搞个前缀和

然后对 \(dfn\) 建线段树

单点改,区间查

屑题卡我半小时常,我现在也不知为啥链式前向星不对

Code

#include<bits/stdc++.h>
#define int long long
using namespace std;
namespace yspm{
	inline int read()
	{
		int res=0,f=1; char k;
		while(!isdigit(k=getchar())) if(k==‘-‘) f=-1;
		while(isdigit(k)) res=res*10+k-‘0‘,k=getchar();
		return res*f;
	}
	inline int max(int x,int y){return x>y?x:y;}
	const int N=1e5+10;
	int val[N];
	struct tree{
		int l,r,maxx,add;
		#define l(p) t[p].l
		#define r(p) t[p].r
		#define maxx(p) t[p].maxx
		#define add(p) t[p].add
	}t[N<<2];
	vector<int> g[N];
	inline void build(int p,int l,int r)
	{
		l(p)=l; r(p)=r; add(p)=0;
		if(l==r) return maxx(p)=val[l],void();
		int mid=(l+r)>>1; build(p<<1,l,mid); build(p<<1|1,mid+1,r);
		maxx(p)=max(maxx(p<<1),maxx(p<<1|1));
		return ;
	}
	inline void spread(int p)
	{
		if(add(p))
		{
			maxx(p<<1)+=add(p); maxx(p<<1|1)+=add(p);
			add(p<<1)+=add(p); add(p<<1|1)+=add(p);
			add(p)=0;
		}return ;
	}
	inline void change(int p,int l,int r,int d)
	{
		if(l(p)>=l&&r(p)<=r)
		{
			add(p)+=d; maxx(p)+=d;
			return ;
		} spread(p);
		int mid=(l(p)+r(p))>>1;
		if(l<=mid) change(p<<1,l,r,d);
		if(r>mid) change(p<<1|1,l,r,d);
		maxx(p)=max(maxx(p<<1),maxx(p<<1|1));
		return ;
	}
	inline int ask(int p,int l,int r)
	{
		if(l<=l(p)&&r(p)<=r) return maxx(p);
		spread(p); int mid=(l(p)+r(p))>>1;
		int ans=-1e15-10;
		if(l<=mid) ans=max(ans,ask(p<<1,l,r));
		if(r>mid) ans=max(ans,ask(p<<1|1,l,r));
		maxx(p)=max(maxx(p<<1),maxx(p<<1|1));
		return ans;
	}
	int tot,l[N],r[N],p[N],n,m;
	inline void dfs(int x,int fa)
	{
		l[x]=++tot; val[l[x]]=p[x]+val[l[fa]];
		int sz=g[x].size();
		for(int i=0;i<sz;++i) if(g[x][i]!=fa) dfs(g[x][i],x);
		r[x]=tot;
		return ;
	}
	int num;
	inline void work()
	{
		for(int i=1;i<=n;++i) g[i].clear();
		memset(t,0,sizeof(t)); memset(val,0,sizeof(val));
		memset(l,0,sizeof(l)); memset(r,0,sizeof(r));
		++num; tot=0;
		printf("Case #%lld:\n",num);
		n=read(); m=read();
		for(int i=1;i<n;++i)
		{
			int u=1+read(),v=1+read();
			g[u].push_back(v); g[v].push_back(u);
		}
		for(int i=1;i<=n;++i) p[i]=read();
		dfs(1,0); build(1,1,n);
		while(m--)
		{
			int opt=read();
			if(opt==1)
			{
				int x=read()+1;
				printf("%lld\n",ask(1,l[x],r[x]));
			}
			else
			{
				int x=read()+1,y=read();
				change(1,l[x],r[x],y-p[x]);
				p[x]=y;
			}
		}
		return ;
	}
	signed main()
	{
		int T=read(); while(T--) work();
		return 0;
	}
}
signed main(){return yspm::main();}

原文地址:https://www.cnblogs.com/yspm/p/12657722.html

时间: 2024-07-30 12:30:28

HDU5692 Snacks的相关文章

HDU5692 Snacks DFS序 线段树

题目 HDU5692 Snacks Problem Description 百度科技园内有n个零食机,零食机之间通过n?1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充,零食机的价值v会时常发生变化.小度熊只能从编号为0的零食机出发,并且每个零食机至多经过一次.另外,小度熊会对某个零食机的零食有所偏爱,要求路线上必须有那个零食机. 为小度熊规划一个路线,使得路线上的价值总和最大. Input 输入数据第一行是一个整数T(T≤10),表示有T组测试数

hdu-5692 Snacks(dfs序+线段树)

题目链接: Snacks Problem Description 百度科技园内有n个零食机,零食机之间通过n−1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充,零食机的价值v会时常发生变化.小度熊只能从编号为0的零食机出发,并且每个零食机至多经过一次.另外,小度熊会对某个零食机的零食有所偏爱,要求路线上必须有那个零食机. 为小度熊规划一个路线,使得路线上的价值总和最大. Input 输入数据第一行是一个整数T(T≤10),表示有TT组测试数据. 对

HDU5692 Snacks DFS+线段树

分析:一棵以1为根的有根树,然后每个点维护从根到当前节点的路径和,当修改一个点时 只会影响的子树的和,最优值也是子树最大的值 #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> using namespace std; typedef long long LL; const int N=1e5+5; const LL INF=1ll*1e11; struc

hdu 5692 Snacks(dfs时间戳+线段树)

Snacks Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2165    Accepted Submission(s): 513 Problem Description 百度科技园内有n个零食机,零食机之间通过n?1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充,零食机的价值v会时常发

HDU5692(线段树+dfs序)

Snacks Time Limit:5000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Description 百度科技园内有n个零食机,零食机之间通过n−1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充,零食机的价值v会时常发生变化.小度熊只能从编号为0的零食机出发,并且每个零食机至多经过一次.另外,小度熊会对某个零食机的零食有所偏爱,要求

hdu 5692 Snacks 线段树+dfs

Snacks Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1295    Accepted Submission(s): 302 Problem Description 百度科技园内有n个零食机,零食机之间通过n−1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充,零食机的价值v会时常发

Snacks

Snacks 题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5692 dfs序+线段树 这道题涉及到对整棵树的值修改,考虑将树状结构用dfs序转化成线性结构,将树的修改转化为区间修改以降低时间复杂度(之前组队赛的时候遇到一道类似的没调出来...代码能力太缺乏了...) 代码如下: 1 #include<cstdio> 2 #include<vector> 3 #include<iostream> 4 #incl

D. Cow and Snacks 并查集

D. Cow and Snacks 题意:有n种小吃,m个人,每个人有两种喜欢的小吃,当一个人遇到两种自己都喜欢的小吃,可以都吃掉,问在最优的吃小吃顺序下,不能吃到自己喜欢的小吃的人数最少是多少? 题解:把n种小吃当作n个点,m个人当作m条边,每个连通图里面第一个吃的人,一定是可以吃两种自己喜欢的小吃.每次判断这条边是否在已有的联通图里面,对已经在连通图里面的边,是一定不能吃到小吃,若不在连通图里面,则一定可以吃到小吃,用cnt统计可以吃到小吃的人数,最后m-cnt就是答案 #include<i

HDU 5692 Snacks

题目链接[http://acm.hdu.edu.cn/showproblem.php?pid=5692] 题意:一棵树,每个节点有权值,有两种操作:1.修改某个点的权值,2.求以x根的子树中的节点到根的权值和的最大值. 题解:DFS序:对点进行重新编号,每个子树中的所有的节点的编号是连续的.映射到线段树上,进行区间修改,区间查询. #include<cstdio> #include<cstring> #include<algorithm> using namespace