Educational Codeforces Round 54 (Rated for Div. 2) E. Vasya and a Tree (树上差分)

E. Vasya and a Tree

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Vasya has a tree consisting of nn vertices with root in vertex 11. At first all vertices has 00 written on it.

Let d(i,j)d(i,j) be the distance between vertices ii and jj, i.e. number of edges in the shortest path from ii to jj. Also, let's denote kk-subtree of vertex xx — set of vertices yy such that next two conditions are met:

  • xx is the ancestor of yy (each vertex is the ancestor of itself);
  • d(x,y)≤kd(x,y)≤k.

Vasya needs you to process mm queries. The ii-th query is a triple vivi, didi and xixi. For each query Vasya adds value xixi to each vertex from didi-subtree of vivi.

Report to Vasya all values, written on vertices of the tree after processing all queries.

Input

The first line contains single integer nn (1≤n≤3⋅1051≤n≤3⋅105) — number of vertices in the tree.

Each of next n−1n−1 lines contains two integers xx and yy (1≤x,y≤n1≤x,y≤n) — edge between vertices xx and yy. It is guarantied that given graph is a tree.

Next line contains single integer mm (1≤m≤3⋅1051≤m≤3⋅105) — number of queries.

Each of next mm lines contains three integers vivi, didi, xixi (1≤vi≤n1≤vi≤n, 0≤di≤1090≤di≤109, 1≤xi≤1091≤xi≤109) — description of the ii-th query.

Output

Print nn integers. The ii-th integers is the value, written in the ii-th vertex after processing all queries.

Examples

input

Copy

5
1 2
1 3
2 4
2 5
3
1 1 1
2 0 10
4 10 100

output

Copy

1 11 1 100 0 

input

Copy

5
2 3
2 1
5 4
3 4
5
2 0 4
3 10 1
1 2 3
2 3 10
1 1 7

output

Copy

10 24 14 11 11 

Note

In the first exapmle initial values in vertices are 0,0,0,0,00,0,0,0,0. After the first query values will be equal to 1,1,1,0,01,1,1,0,0. After the second query values will be equal to 1,11,1,0,01,11,1,0,0. After the third query values will be equal to 1,11,1,100,01,11,1,100,0.

题目大意:

    一棵根为1的树,Q次操作,每次使点x和距离点x一定距离内点的点权都加上W,最后一次性输出所有点的点权。

解法:

    多次修改最后一次性输出答案,可以先考虑下差分做法。

    首先把询问离线,每个点存一下相应操作并给当前点x加上权值W,最后DFS的时候,每进入一层,就把对应的需要减掉的深度权值更新,子树遍历完之后再加回来就可以啦。

Accepted code

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;

#define sc scanf
#define Min(x, y) x = min(x, y)
#define Max(x, y) x = max(x, y)
#define ALL(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define pir pair <int, int>
#define MK(x, y) make_pair(x, y)
#define MEM(x, b) memset(x, b, sizeof(x))
#define MPY(x, b) memcpy(x, b, sizeof(x))
#define lowbit(x) ((x) & -(x))
#define P2(x) ((x) * (x))

typedef long long ll;
const int Mod = 1e9 + 7;
const int N = 3e5 + 100;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
inline ll dpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t) % Mod; b >>= 1; t = (t*t) % Mod; }return r; }
inline ll fpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t); b >>= 1; t = (t*t); }return r; }

vector <pir> ask[N];
vector <int> G[N];
int dep[N], n, q;
ll ans[N], s[N];

void DFS(int x, int fa, int dep) {
	for (auto it : ask[x]) {     // 先做减法
		int d = it.first, w = it.second;
		s[min(N - 1, dep + d + 1)] -= w;
	}
	ans[x] += s[dep];   // 差分
	for (auto v : G[x]) {
		if (v != fa)
			ans[v] += ans[x], DFS(v, x, dep + 1);
	}
	for (auto it : ask[x]) {   // 再做加法
		int d = it.first, w = it.second;
		s[min(N - 1, dep + d + 1)] += w;
	}
}

int main()
{
#ifdef OlaMins
	freopen("D:/input.txt", "r", stdin);
	//freopen("D:/output.txt", "w", stdout);
#endif

	cin >> n;
	for (int i = 1; i < n; i++) {
		int u, v;
		sc("%d %d", &u, &v);
		G[u].push_back(v);
		G[v].push_back(u);
	}
	cin >> q;
	while (q--) {
		int x, k, w;
		sc("%d %d %d", &x, &k, &w);  // 询问离线
		ans[x] += w;
		ask[x].push_back({ k, w });
	}
	DFS(1, 0, 0);

	for (int i = 1; i <= n; i++)
		printf("%lld%c", ans[i], " \n"[i == n]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43851525/article/details/110500560