欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Codeforces - Vasya and a Tree

程序员文章站 2022-05-27 20:09:12
...

题目链接:Codeforces - Vasya and a Tree


如果是简单的子树加减,那么直接dfs序+Fenwick就可以解决。

现在,子树加上了一个深度的限制。我们似乎可以从上到下,用主席树合并答案。实际上也是可以的。

但是我们有一个简单的做法,就是利用dfs,每次进入子树的时候维护Fenwick,出子树的时候清除影响,就利用小空间达到和主席树一样的效果了。


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3e5+10;
int n,m,res[N],d[N],dep[N];
vector<int> g[N];	vector<pair<int,int>> v[N];
inline void add(int a,int b){g[a].push_back(b),g[b].push_back(a);}
inline void insert(int x,int v){for(;x<=n;x+=x&(-x)) d[x]+=v;}
inline int ask(int x){int s=0; for(;x;x-=x&(-x)) s+=d[x]; return s;}
void dfs(int x,int fa){
	dep[x]=dep[fa]+1;
	for(auto to:v[x])	insert(dep[x],to.second),insert(dep[x]+to.first+1,-to.second);
	res[x]=ask(dep[x]);
	for(auto to:g[x])	if(to!=fa)	dfs(to,x);
	for(auto to:v[x])	insert(dep[x],-to.second),insert(dep[x]+to.first+1,to.second);
}
signed main(){
	cin>>n;
	for(int i=1,x,y;i<n;i++)	scanf("%lld %lld",&x,&y),add(x,y);
	cin>>m;
	for(int i=1,p,d,x;i<=m;i++)	scanf("%lld %lld %lld",&p,&d,&x),v[p].push_back({d,x});
	dfs(1,1);
	for(int i=1;i<=n;i++)	printf("%lld ",res[i]);
	return 0;
}