Educational Codeforces Round 54 (Rated for Div. 2): E. Vasya and a Tree(DFS+差分)

版权声明:本文为博主原创文章,你们可以随便转载 https://blog.csdn.net/Jaihk662/article/details/84029477

题意:

给你一棵n个节点的树,每个点有一个权值,初始全为0,m次操作,每次三个数(v, d, x)表示只考虑以v为根的子树,将所有与v点距离小于等于d的点权值全部加上x,求所有操作完毕后,所有节点的值

思路:

O(n)DFS一遍即可,既然只用最后输出答案,果断离线,存下每个点的所有操作

设deep[x]为x点的深度

  • 当第一次DFS到点v时,将深度在deep[v]到deep[v+d]的点权值全部加上x
  • 当搜完点v所有的子孙准备回溯时,将深度在deep[v]到deep[v+d]的点权值全部减去x
  • 这样每次搜到点v,当前深度的总权值就是答案

以上可以用BIT解决,当然也可以直接差分

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define LL long long
#define mod 1000000007
typedef struct Res
{
	LL val;
	int dep;
}Res;
Res s[300005];
vector<int> G[300505];
vector<Res> F[300505];
int n;
LL ans[300505], out[300505];
void Sech(int u, int p, int deep, LL val)
{
	Res now;
	int i, v;
	for(i=0;i<F[u].size();i++)
	{
		now = F[u][i];
		out[deep] += now.val, out[min(deep+now.dep+1, n+5)] -= now.val;
	}
	val += out[deep];
	//printf("%d %d %lld %lld\n", u, deep, out[deep], val);
	ans[u] = val;
	for(i=0;i<G[u].size();i++)
	{
		v = G[u][i];
		if(v==p)
			continue;
		Sech(v, u, deep+1, val);
	}
	for(i=0;i<F[u].size();i++)
	{
		now = F[u][i];
		out[deep] -= now.val, out[min(deep+now.dep+1, n+5)] += now.val;
	}
}
int main(void)
{
	Res now;
	int m, i, x, y;
	scanf("%d", &n);
	for(i=1;i<=n-1;i++)
	{
		scanf("%d%d", &x, &y);
		G[x].push_back(y);
		G[y].push_back(x);
	}
	scanf("%d", &m);
	for(i=1;i<=m;i++)
	{
		scanf("%d%d%lld", &x, &y, &now.val);
		now.dep = y;
		F[x].push_back(now);
	}
	Sech(1, 0, 1, 0ll);
	for(i=1;i<=n;i++)
		printf("%lld ", ans[i]);
	puts("");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Jaihk662/article/details/84029477