CF1076E:树状数组 + dfs

CF1076E

题意:给你一棵以1为根的树,每次把以x为根,深度不大于k的点的值全部加上v。最后求每个结点的值。

题解

  • dfs从根开始遍历,那么遍历到每一个点,其深度是确定的。
  • x根的深度为dep,深度不大于k的点都加上v,相当于c[dep] + v,c[dep+k+1]-v,差分处理。
  • 最后x根处理完之后,还有c[dep]-v,c[dep+k+1] + v。因为要遍历其它根,都在同一层,排除这个根的影响。

代码

#include <bits/stdc++.h>
using namespace std;
#define sd second
#define ft first
typedef long long ll;
typedef pair<int,int>pii;
int const N = 300000 + 10;
int n,m;
ll c[N],ans[N];
vector<int>G[N];
vector<pii>p[N];
int lowbit(int x){return x&-x;}
void add(int i,int x){	
	while(i <= N){
		c[i] += x;
		i += lowbit(i);
	}
}
ll query(int i){
	ll sum = 0;
	while(i){
		sum += c[i];
		i -= lowbit(i);
	}
	return sum;
}
void dfs(int u,int fa,int dep){
	for(int i=0;i<p[u].size();i++){
		add(dep,p[u][i].sd);
		add(dep+p[u][i].ft+1,-p[u][i].sd);
	}
	ans[u] = query(dep);
	for(int i=0;i<G[u].size();i++){
		int v = G[u][i];
		if(v == fa)	continue;
		dfs(v,u,dep+1);
	}
	for(int i=0;i<p[u].size();i++){
		add(dep,-p[u][i].sd);
		add(dep+p[u][i].ft+1,p[u][i].sd);
	}
}
int main(){
	scanf("%d",&n);
	for(int i=0;i<n-1;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		G[u].push_back(v);
		G[v].push_back(u);
	}
	scanf("%d",&m);
	for(int i=0;i<m;i++){
		int u,dep,val;  
		scanf("%d%d%d",&u,&dep,&val);
		p[u].push_back(pii(dep,val));
	}
	dfs(1,0,1);
	for(int i=1;i<=n;i++)
		printf("%lld ",ans[i]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42264485/article/details/89172273