神奇写法90pts求调
查看原帖
神奇写法90pts求调
1261547
belif__kibo楼主2024/8/9 17:33
#include<bits/stdc++.h>
#define int long long int
using namespace std;
int n,k,s[100010],sum[100010][30],fa[100010];
vector<int> e[100010];
void dfs(int p)
{
	for(int i=0;i<=k;i++) sum[p][i]=s[p];
	for(int i=0;i<e[p].size();i++)
	{
		int v=e[p][i];
		if(v!=fa[p])
		{
			fa[v]=p;
			dfs(v);
			for(int j=1;j<=k;j++) sum[p][j]+=sum[v][j-1];
		}
	}
}
signed main()
{
	scanf("%lld%lld",&n,&k);
	for(int i=1;i<=n-1;i++)
	{
		int u,v;
		scanf("%lld%lld",&u,&v);
		e[u].push_back(v);
		e[v].push_back(u);
	}
	for(int i=1;i<=n;i++) scanf("%lld",&s[i]);
	dfs(1);
	for(int i=1;i<=n;i++)
	{
		int len=k,ans=0,p=i,f=fa[i];
		ans+=sum[i][len];
		while(len--&&f!=0)
		{
			ans+=sum[f][0];
			if(len)
			{
				for(int j=0;j<e[f].size();j++)
				{
					int v=e[f][j];
					if(v!=fa[f]&&v!=p) ans+=sum[v][len-1];
				}
			}
			p=f;
			f=fa[p];
		}
		printf("%lld\n",ans);
	}
}

大概思路是把这棵树当做以点1为根,然后预处理数组sum[i][j]存储点i的子树中所有节点(包括点i自己)中距离点i不大于k的所有点的权值和。在求解过程中先加上sum[i][k],然后向父亲节点上溯到根节点(或距离i超过k时跳出),用同样的方法统计结果。T了#3,求调

2024/8/9 17:33
加载中...