题目内容
给定一个 n n n 个点的有根树, Q Q Q 次操作,每次操作将点 p p p 的子树中所有点都加 x x x ,问操作后每个点的权值是多少,初始每个点的权值都是 0 0 0
数据范围
- 2 ≤ n , Q ≤ 2 ⋅ 1 0 5 2\leq n,Q\leq 2\cdot 10^5 2≤n,Q≤2⋅105
- 1 ≤ p ≤ n 1\leq p\leq n 1≤p≤n
- 1 ≤ x ≤ 1 0 4 1\leq x\leq 10^4 1≤x≤104
题解
因为是有根树,所以按照从根到每个叶子的方式遍历,每个儿子累加上其父亲的权值即可。
时间复杂度: O ( n ) O(n) O(n)
代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, Q;
cin >> n >> Q;
vector<vector<int>> g(n);
for (int i = 1; i < n; ++i) {
int a, b;
cin >> a >> b;
a--, b--;
g[a].push_back(b);
g[b].push_back(a);
}
vector<int> val(n, -1);
vector<int> add(n, 0);
for (int i = 0; i < Q; ++i) {
int p, x;
cin >> p >> x;
p--;
add[p] += x;
}
queue<int> q;
val[0] = add[0];
q.push(0);
while (!q.empty()) {
int u = q.front(); q.pop();
for (int v: g[u]) {
if (val[v] == -1) {
val[v] = val[u] + add[v];
q.push(v);
}
}
}
for (int i = 0; i < n; ++i) cout << val[i] << " \n"[i + 1 == n];
return 0;
}