E. Vasya e uma árvore
limite de tempo por teste
2 segundos
limite de memória por teste
256 megabytes
entrada
entrada padrão
resultado
saída padrão
Vasya tem uma árvore consistindo de nn vértices com raiz no vértice 11. A princípio, todos os vértices têm 00 escrito nele.
Seja d (i, j) d (i, j) a distância entre os vértices ii e jj, ou seja, o número de arestas no caminho mais curto de ii a jj. Além disso, vamos denotar kk-subárvore do vértice xx - conjunto de vértices yy de modo que as próximas duas condições sejam atendidas:
- xx é o ancestral de yy (cada vértice é o ancestral de si mesmo);
- d (x, y) ≤kd (x, y) ≤k.
Vasya precisa de você para processar consultas mm. A segunda consulta é um vivi, didi e xixi triplo. Para cada consulta, Vasya adiciona o valor xixi a cada vértice da didi-subárvore de vivi.
Relate ao Vasya todos os valores, escritos nos vértices da árvore após o processamento de todas as consultas.
Entrada
A primeira linha contém um único inteiro nn (1≤n≤3⋅1051≤n≤3⋅105) - número de vértices na árvore.
Cada uma das próximas n − 1n − 1 linhas contém dois inteiros xx e yy (1≤x, y≤n1≤x, y≤n) - aresta entre os vértices xx e yy. É garantido que determinado gráfico é uma árvore.
A próxima linha contém um único inteiro mm (1≤m≤3⋅1051≤m≤3⋅105) - número de consultas.
Cada uma das próximas linhas mm contém três inteiros vivi, didi, xixi (1≤vi≤n1≤vi≤n, 0≤di≤1090≤di≤109, 1≤xi≤1091≤xi≤109) - descrição do ii- ª consulta.
Resultado
Imprime nn inteiros. O ii-ésimo inteiros é o valor, escrito no ii-ésimo vértice depois de processar todas as consultas.
Exemplos
entrada
cópia de
5
1 2
1 3
2 4
2 5
3
1 1 1
2 0 10
4 10 100
resultado
cópia de
1 11 1 100 0
entrada
cópia de
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
resultado
cópia de
10 24 14 11 11
Nota
No primeiro exemplo, os valores iniciais nos vértices são 0,0,0,0,00,0,0,0,0. Após a primeira consulta os valores serão iguais a 1,1,1,0,01,1,1,0,0. Após a segunda consulta os valores serão iguais a 1,11,1,0,01,11,1,0,0. Após a terceira consulta, os valores serão iguais a 1,11,1,100,01,11,1,100,0.
Ideia principal:
Uma árvore com uma raiz de 1, operações Q, cada ponto de tempo xe o peso do ponto dentro de uma certa distância do ponto x são adicionados com W e, finalmente, os pesos dos pontos de todos os pontos são produzidos de uma vez.
solução:
Se você modificar a resposta de saída final várias vezes, poderá considerar o método de diferença primeiro.
Primeiro, coloque a consulta off-line, salve a operação correspondente para cada ponto e adicione o peso W ao ponto x atual. No final do DFS, cada vez que ele entra em uma camada, o peso de profundidade correspondente que precisa ser subtraído é atualizado e a subárvore é percorrida. Adicione novamente mais tarde.
Código aceito
#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;
}