灵力之泉

灵力之泉

https://ac.nowcoder.com/acm/contest/11196/C

换根dp{dp}.

首先我们假如知道子树相连点的答案,我们肯定优先选择最大的.

dpdp方程为:fu=max(fu,fv+i/wu+1).f_u=max(f_u,f_v+i/w_u+1). ii表示第i大的fvf_v.

通过树形dpdp转移后.那么紧接着就是换根dpdp了,考虑如何通过父亲节点得到子节点的答案,可以通过前后缀的形式,我通过把父亲节点的所有子节点做个前缀和后缀,然后转移得到在这个节点当根节点时候,父亲节点相邻对它的贡献gug_u.

然后就解决了.

code:

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int w[N],f[N],ans[N],pre[N],suf[N],g[N];
vector<int>G[N];

void dfs(int u,int fa)
{
	vector<int>temp;
	for(int v:G[u])
	{
		if(v==fa)	continue;
		dfs(v,u);
		temp.push_back(f[v]);
	}
	sort(temp.begin(),temp.end());
	reverse(temp.begin(),temp.end());
	for(int i=0;i<(int)temp.size();i++)
	{
		int v=temp[i];
		f[u]=max(f[u],v+i/w[u]+1);
	}
}

void DFS(int u,int fa)
{
	vector<pair<int,int> >temp;
	temp.push_back({g[u],u});
	for(int v:G[u])
	{
		if(v==fa)	continue;
		temp.push_back({f[v],v});
	}
	sort(temp.begin(),temp.end());
	reverse(temp.begin(),temp.end());
	int cnt=(int)temp.size();
	suf[cnt]=0;
	for(int i=cnt-1;i>=0;i--)
		suf[i]=max(suf[i+1],temp[i].first+(i-1)/w[u]+1);
	for(int i=0;i<cnt;i++)
	{
		pre[i]=temp[i].first+i/w[u]+1;
		if(i)	pre[i]=max(pre[i],pre[i-1]);
		if(temp[i].second!=u)
		{
			int x=temp[i].second;
			g[x]=suf[i+1];
			if(i)	g[x]=max(g[x],pre[i-1]);
		}
	}
	ans[u]=pre[cnt-1];
	//记录当i作为根节点 此时u中比它小的后缀最大值,因为i不算u的节点  
	for(int v:G[u])
	{
		if(v==fa)	continue;
		DFS(v,u);
	}
}

int main()
{
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&w[i]);
	for(int i=1;i<n;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		G[u].push_back(v);
		G[v].push_back(u);
	}
	dfs(1,1);
	g[1]=-1;
	DFS(1,1);
	for(int i=1;i<=n;i++)
		printf("%d\n",ans[i]);
	return 0;
}

lpt的小屋 文章被收录于专栏

我想要一份甜甜的爱情

全部评论

相关推荐

不愿透露姓名的神秘牛友
10-12 10:48
已编辑
秋招之苟:邻居家老哥19届双2硕大厂开发offer拿遍了,前几天向他请教秋招,他给我看他当年的简历,0实习实验室项目技术栈跟开发基本不沾边😂,我跟他说这个放在现在中厂简历都过不了
点赞 评论 收藏
分享
菜菜咪:1. 可以使用简历网站的模版,美观度会更好一点 2. 邮箱可以重新申请一个,或者用qq邮箱的别名,部分hr可能会不喜欢数字邮箱 3. 项目经历最好分点描述,类似的项目很多,可以参考一下别人怎么写的 4. 自我评价可加可不加,技术岗更看重技术。最后,加油,优秀士兵
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务