【题 解】 CF915F : Valor de desequilibrio de un árbol

Asunto original
∑ i = 1 n ∑ j = 1 n I (i, j) \ sum_ {i = 1} ^ {n} \ sum_ {j = 1} ^ {n} I (i, j)i = 1nj = 1nYo ( yo ,j )
= ∑ yo = 1 norte ∑ j = 1 norte M eje (yo, j) - ∑ yo = 1 norte ∑ j = 1 norte M en (yo, j) = \ sum_ {i = 1} ^ {n} \ sum_ {j = 1} ^ {n} Max (i, j) - \ sum_ {i = 1} ^ {n} \ sum_ {j = 1} ^ {n} Min (i, j)=i = 1nj = 1nM a x ( yo ,j )-i = 1nj = 1nM i n ( yo ,j )
Calcular los valores de las dos partes por separado, considerar el conjunto de verificación de unión y
fusionar. Para una arista, esta arista tiene dos pesos conectados a dos puntos, si queremos calcularMax (i, j) Max (i, j)M a x ( yo ,J ) , entonces estos pesos de borde son pesos que grandes dos puntos, de acuerdo con los pesos de borde en orden ascendente, y luego verifique y establezca simultáneamente el registro de dos bloques es el número de puntos que se han comunicado
para buscarM ax (i, j) Máx (i, j)M a x ( yo ,En el caso de j ) , dado que se enumera de pequeño a grande, se garantiza que el borde que se conectará es el más grande actual, por lo que el valor máximo actual en todas las rutas relevantes es él mismo, así que solo use el principio de multiplicación para calcular directamente

M en (i, j) Min (i, j) M i n ( yo ,j ) De la misma forma, el peso de la arista es el menor de los dos puntos, y luego se ordena de mayor a menor, y se vuelve a hacer si es casi igual

Código:

#include <bits/stdc++.h>
#define maxn 1000010
#define LL long long
using namespace std;
struct Line{
    
    
	int x, y;
	LL l1, l2;
}line[maxn];
LL num[maxn];
int f[maxn], n, a[maxn];

inline int read(){
    
    
	int s = 0, w = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
	for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
	return s * w;
}

bool cmp1(Line x, Line y){
    
     return x.l2 < y.l2; }
bool cmp2(Line x, Line y){
    
     return x.l1 > y.l1; }
int getfa(int k){
    
     return f[k] == k ? k : f[k] = getfa(f[k]); }

int main(){
    
    
	n = read();
	for (int i = 1; i <= n; ++i) a[i] = read();
	for (int i = 1; i < n; ++i){
    
    
		int x = read(), y = read();
		line[i].x = x, line[i].y = y;
		line[i].l1 = min(a[x], a[y]), line[i].l2 = max(a[x], a[y]);
	}
	LL ans = 0;
	sort(line + 1, line + n, cmp1);
	for (int i = 1; i <= n; ++i) f[i] = i, num[i] = 1;
	for (int i = 1; i < n; ++i){
    
    
		int x = line[i].x, y = line[i].y, s1 = getfa(x), s2 = getfa(y);
	//	printf("%d %d %lld\n", x, y, line[i].l2);
		if (s1 == s2) continue;
		ans += num[s1] * num[s2] * line[i].l2;
		f[s2] = s1, num[s1] += num[s2];
	}
	sort(line + 1, line + n, cmp2);
	for (int i = 1; i <= n; ++i) f[i] = i, num[i] = 1;
	for (int i = 1; i < n; ++i){
    
    
		int x = line[i].x, y = line[i].y, s1 = getfa(x), s2 = getfa(y);
	//	printf("%d %d %lld\n", x, y, line[i].l1);
		if (s1 == s2) continue;
		ans -= num[s1] * num[s2] * line[i].l1;
		f[s2] = s1, num[s1] += num[s2];
	}
	printf("%lld\n", ans);
	return 0;
}

Supongo que te gusta

Origin blog.csdn.net/ModestCoder_/article/details/108523040
Recomendado
Clasificación