Educación Codeforces Ronda 54 (Clasificado para Div.2) E. Vasya y un árbol (树上 差分)

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;
}

 

Supongo que te gusta

Origin blog.csdn.net/weixin_43851525/article/details/110500560
Recomendado
Clasificación