CF1076E Vasya and a Tree

可以把操作离线,每次开始遍历到一个节点,把以它为根的操作加上,结束时把这个点的操作删去。

因为是\(dfs\),所以一个点对同一深度的贡献是一定的,可以用树状数组区间加减,求前缀和。

但是因为是\(dfs\),完全可以把前缀和传入,就不需要树状数组了。

#define B cout << "BreakPoint" << endl;
#define O(x) cout << #x << " " << x << endl;
#define O_(x) cout << #x << " " << x << " ";
#define Msz(x) cout << "Sizeof " << #x << " " << sizeof(x)/1024/1024 << " MB" << endl;
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
#define LL long long
const int inf = 1e9 + 9;
const int N = 6e5 + 5;
using namespace std;
inline int read() {
	int s = 0,w = 1;
	char ch = getchar();
	while(ch < '0' || ch > '9') {
		if(ch == '-')
			w = -1;
		ch = getchar();
	}
	while(ch >= '0' && ch <= '9') {
		s = s * 10 + ch - '0';
		ch = getchar();
	}
	return s * w;
}
int head[N],to[N],nxt[N],cnt;
void add(int x,int y) {
	to[++cnt] = y;
	nxt[cnt] = head[x];
	head[x] = cnt;
}
int n,m;
struct node {
	int d,x;
	inline node() {}
	inline node(int __d, int __x) :d(__d), x(__x){}
};
vector<node> s[N];
LL c[N],ans[N];
void dfs(int u,int fa,int dep,LL sum) {
	for(auto it = s[u].begin();it != s[u].end();it++) {
		c[dep] += it->x;
		if(dep + it->d + 1 <= n) c[dep + it->d + 1] -= it->x;
	}
	sum += c[dep],ans[u] = sum;
	for(int i = head[u];i;i = nxt[i]) {
		int v = to[i];
		if(v != fa) dfs(v,u,dep + 1,sum);
	}
	for(auto it = s[u].begin();it != s[u].end();it++) {
		c[dep] -= it -> x;
		if(dep + it -> d + 1 <= n) c[dep + it -> d + 1] += it -> x;
	}
}
int main() {
	n = read();
	for(int i = 1;i < n;i++) {
		int x = read(),y = read();
		add(x,y),add(y,x);
	}
	m = read();
	for(int i = 1;i <= m;i++) {
		int v = read(),d = read(),x = read();
		s[v].push_back(node(d,x));
	}
	dfs(1,0,0,0);
	for(int i = 1;i <= n;i++) printf("%lld ", ans[i]);
	return 0;
}
posted @ 2020-03-04 17:43  优秀的渣渣禹  阅读(92)  评论(0编辑  收藏  举报