Vasya and a Tree
Problem Description
Vasya has a tree consisting of n vertices with root in vertex 1. At first all vertices has 0 written on it.
Let d(i,j)d(i,j)d(i,j) be the distance between vertices i and j, i.e. number of edges in the shortest path from i to j. Also, let’s denote k-subtree of vertex x — set of vertices y such that next two conditions are met:
- x is the ancestor of y (each vertex is the ancestor of itself);
- d(x,y)≤kd(x,y)≤kd(x,y)≤k.
Vasya needs you to process m queries. The i-th query is a triple vi, di and xi. For each query Vasya adds value xi to each vertex from di-subtree of vi.
Report to Vasya all values, written on vertices of the tree after processing all queries.
Input
The first line contains single integer n (1≤n≤3⋅105) — number of vertices in the tree.
Each of next n−1 lines contains two integers x and y (1≤x,y≤n) — edge between vertices x and y. It is guarantied that given graph is a tree.
Next line contains single integer m (1≤m≤3⋅105) — number of queries.
Each of next m lines contains three integers vi, di, xi (1≤vi≤n, 0≤di≤109, 1≤xi≤109) — description of the i-th query.
Output
Print n integers. The i-th integers is the value, written in the i-th vertex after processing all queries.
Sample Input
5
1 2
1 3
2 4
2 5
3
1 1 1
2 0 10
4 10 100
Sample Output
1 11 1 100 0
题意
一棵以1号为根,共有n个节点的树,每个节点初始值为0。每次操作可以将以u为根的子树中与其距离不超过k的所有节点都加上x,求所有操作完成后每个节点的值。
题解:
DFS,对于每个节点,假设当前节点u,深度为height。设add[i] 表示深度为i开始需要加的x的和。那个对于从u开始的每操作,DFS向下时,可以令add[heigeht]+=xadd[heigeht] += xadd[heigeht]+=x , add[height+k+1]−=xadd[height+k+1] -= xadd[height+k+1]−=x,然后递归向下时,设累加变量sum加上add[u]。同时在u递归结束时,需要将add对应的部分进行加减,以消去u的影响。
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<ctype.h>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<iterator>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define eps 1e-8
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int maxn = 300100;
const int mod = 1000000007;
LL add[maxn], ans[maxn];
vector<int> g[maxn];
vector<P> que[maxn];
void dfs(int u, int hei, int fa, LL sum);
int main()
{
int n, m, f, t, i;
scanf("%d", &n);
for(i=1;i<n;i++){
scanf("%d %d", &f, &t);
g[f].push_back(t);
g[t].push_back(f);
}
scanf("%d", &m);
for(i=0;i<m;i++)
{
int w;
scanf("%d %d %d", &f, &t, &w);
que[f].push_back(P(t, w));
}
dfs(1, 0, 0, 0);
for(i=1;i<=n;i++)
{
if(i>1)printf(" ");
printf("%I64d", ans[i]);
}
printf("\n");
return 0;
}
void dfs(int u, int hei, int fa, LL sum)
{
int i;
for(i=0;i<que[u].size();i++)
{
int h = min(hei + que[u][i].first+1, maxn-10);
add[hei] += que[u][i].second;
add[h] -= que[u][i].second;
}
sum += add[hei];
ans[u] = sum;
for(i=0;i<g[u].size();i++)
if(g[u][i] != fa)
dfs(g[u][i], hei+1, u, sum);
for(i=0;i<que[u].size();i++)
{
int h = min(hei + que[u][i].first+1, maxn-10);
add[hei] -= que[u][i].second;
add[h] += que[u][i].second;
}
}
探讨在一棵以1号节点为根的树上,如何高效处理一系列操作,即对特定节点及其子树中距离不超过预设值的所有节点进行值更新,最终求得每个节点的总更新值。通过深度优先搜索(DFS)算法与动态规划思想,实现快速求解。
493

被折叠的 条评论
为什么被折叠?



