E.ヴァシャと木
テストごとの制限時間
2秒
テストごとのメモリ制限
256メガバイト
入力
標準入力
出力
標準出力
Vasyaには、頂点11にルートを持つnn個の頂点で構成されるツリーがあります。最初は、すべての頂点に00が書き込まれています。
d(i、j)d(i、j)を頂点iiとjjの間の距離、つまりiiからjjへの最短経路のエッジの数とします。また、次の2つの条件が満たされるように、頂点xxのkkサブツリー—頂点yyのセットを示しましょう。
- xxはyyの祖先です(各頂点はそれ自体の祖先です)。
- d(x、y)≤kd(x、y)≤k。
Vasyaでは、mmクエリを処理する必要があります。2番目のクエリは、トリプルvivi、didi、およびxixiです。クエリごとに、Vasyaはviviのdidiサブツリーから各頂点に値xixiを追加します。
すべてのクエリを処理した後、ツリーの頂点に書き込まれたすべての値をVasyaに報告します。
入力
最初の行には、単一の整数nn(1≤n≤3⋅1051≤n≤3⋅105)—ツリー内の頂点の数が含まれています。
次のn-1n-1行のそれぞれには、2つの整数xxとyy(1≤x、y≤n1≤x、y≤n)—頂点xxとyyの間のエッジが含まれます。与えられたグラフがツリーであることが保証されます。
次の行には、単一の整数mm(1≤m≤3⋅1051≤m≤3⋅105)—クエリの数が含まれています。
次のmm行のそれぞれには、3つの整数vivi、didi、xixi(1≤vi≤n1≤vi≤n、0≤di≤1090≤di≤109、1≤xi≤1091≤xi≤109)が含まれています—ii-の説明クエリ。
出力
nn個の整数を出力します。ii番目の整数は、すべてのクエリを処理した後にii番目の頂点に書き込まれる値です。
例
入力
コピー
5
1 2
1 3
2 4
2 5
3
1 1 1
2 0 10
4 10 100
出力
コピー
1 11 1 100 0
入力
コピー
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
出力
コピー
10 24 14 11 11
注意
最初の例では、頂点の初期値は0,0,0,0,00,0,0,0,0です。最初のクエリの後、値は1,1,1,0,01,1,1,0,0に等しくなります。2番目のクエリの後、値は1,11,1,0,01,11,1,0,0に等しくなります。3番目のクエリの後、値は1,11,1,100,01,11,1,100,0に等しくなります。
本旨:
ルートが1、Q演算、各時点x、およびポイントxから一定の距離内にあるポイントの重みを持つツリーにWが加算され、最後にすべてのポイントのポイントの重みが一度に出力されます。
解決:
最終的な出力回答を数回変更する場合は、最初に差分方法を検討できます。
まず、クエリをオフラインにし、各ポイントに対応する操作を保存して、現在のポイントxに重みWを追加します。DFSの最後で、レイヤーに入るたびに、減算する必要のある対応する深度の重みが更新され、サブツリーがトラバースされます。後で追加し直します。
受け入れられたコード
#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;
}