E. Vasya y un árbol
límite de tiempo por prueba
2 segundos
límite de memoria por prueba
256 megabytes
entrada
entrada estándar
salida
salida estándar
Vasya tiene un árbol que consta de nn vértices con raíz en el vértice 11. Al principio, todos los vértices tienen 00 escrito en él.
Sea d (i, j) d (i, j) la distancia entre los vértices ii y jj, es decir, el número de aristas en el camino más corto de ii a jj. Además, denotemos kk-subárbol del vértice xx - conjunto de vértices yy tal que se cumplan las siguientes dos condiciones:
- xx es el antepasado de yy (cada vértice es el antepasado de sí mismo);
- d (x, y) ≤kd (x, y) ≤k.
Vasya necesita que procese las consultas de mm. La segunda consulta es un triple vivi, didi y xixi. Para cada consulta, Vasya agrega valor xixi a cada vértice del subárbol didi de vivi.
Informe a Vasya todos los valores, escritos en los vértices del árbol después de procesar todas las consultas.
Entrada
La primera línea contiene un número entero nn (1≤n≤3⋅1051≤n≤3⋅105) - número de vértices en el árbol.
Cada una de las siguientes n − 1n − 1 líneas contiene dos números enteros xx y yy (1≤x, y≤n1≤x, y≤n) - borde entre los vértices xx e yy. Se garantiza que el gráfico dado es un árbol.
La siguiente línea contiene un número entero mm (1≤m≤3⋅1051≤m≤3⋅105) - número de consultas.
Cada una de las siguientes líneas de mm contiene tres enteros vivi, didi, xixi (1≤vi≤n1≤vi≤n, 0≤di≤1090≤di≤109, 1≤xi≤1091≤xi≤109) - descripción de la ii- a consulta.
Salida
Imprime nn enteros. El segundo entero es el valor, escrito en el segundo vértice después de procesar todas las consultas.
Ejemplos
entrada
Copiar
5
1 2
1 3
2 4
2 5
3
1 1 1
2 0 10
4 10 100
salida
Copiar
1 11 1 100 0
entrada
Copiar
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
salida
Copiar
10 24 14 11 11
Nota
En el primer ejemplo, los valores iniciales en los vértices son 0,0,0,0,00,0,0,0,0. Después de la primera consulta, los valores serán iguales a 1,1,1,0,01,1,1,0,0. Después de la segunda consulta, los valores serán iguales a 1,11,1,0,01,11,1,0,0. Después de la tercera consulta, los valores serán iguales a 1,11,1,100,01,11,1,100,0.
Idea principal:
Un árbol con una raíz de 1, operaciones Q, cada punto de tiempo x y el peso del punto dentro de una cierta distancia del punto x se agregan con W, y finalmente los pesos de todos los puntos se generan a la vez.
solución:
Si modifica la respuesta de salida final varias veces, puede considerar primero el método de diferencia.
Primero, desconecte la consulta, guarde la operación correspondiente para cada punto y agregue el peso W al punto actual x. Al final del DFS, cada vez que ingresa a una capa, se actualiza el peso de profundidad correspondiente que debe restarse y se recorre el subárbol. Agréguelo más tarde.
Codigo aceptado
#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;
}