[Pregunta solución] LuoGu6623: [El examen conjunto de elecciones provinciales 2020 Un volumen] Árbol

El portal de preguntas original.
Considere la contribución del número en un punto al todo.
Debido a que es o, considere la contribución de cada dígito de un cierto número al total.
Suma el número en un punto a 3, suma este 3 y sus antepasados Escribe la forma de contribución. El
número de dígitos de derecha a izquierda es 0123 ...
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000
9 1001
10 1010
11 1011
12 1100
13 1101
14 1110
15 1111.
Saca el primer número binario por separado y encuentra que es Regular: 1001100110011 …… El
primer lugar, 01 tiene una longitud de bucle de 2 2 2 ^ 222. En cada sección de bucle, 0/1 repite2 1 2 ^ 12Una vez , para el2 1 2 ^ 1cuyo valor de dígito es 1.21 número puedo producirxor 2 1 xor2 ^ 1x o r 21 contribuido
por la extensión
k-ésimo bit, la duración del ciclo de la sección 01 es2 k + 1 2 ^ {k2k + 1 , en cada sección del ciclo, 0/1 repite2 k 2 ^ k2k veces, para2 k 2 ^ kcuyo valor de dígito es 1.2k número puedo producirxor 2 k xor2 ^ kx o r 2La contribución de k
se puede diferenciar en el árbol. Para cada bit, el primer1 1 encada nodo cíclico1 posición o más2 k 2 ^ k2k , el primer0 0La posición de 0 también es2 k 2 ^ k2k , lo que significa que el valor de un segmento es1 1El intervalo de 1 también puede ser de hasta2 k 2 ^ k2k
Luego continúe optimizando la diferencia y encuentre el subíndiceiide la matriz de diferencias a cambiaryo , por elkkk bits, siempre satisfaceni mod 2 k = 0 i \ text {mod} 2 ^ k = 0yo  mod  2k=0i y (2 k - 1) = 0 i \ text {y} (2 ^ k-1) = 0yo  y  ( 2k-1 )=0
Por un punto, para averiguar qué antepasados ​​propios pueden ser también o, puede utilizar la profundidad para describir
si el propio pesoau a_uunaen, Más la diferencia de profundidad entre el antepasado y él mismo deltad delta_dd e l t ad, 即au + delta a_u + delta_dunaen+d e l t ad¿Es el ii mencionado anteriormente?yo , pero endfs dfsEn el proceso de d f s , solo puedes estar "relacionado contigo mismo" cada vez, lo que se transforma enau + du y dv para una congruencia de 2 k a_u + d_u y d_v para una congruencia de 2 ^ kunaen+reenCon dvPara hasta 2k conmás quedondevvv ShiuuEl antepasado de u , la
diferencia en el subárbol esO (nlogn) O (nlogn)O ( n l o g n )

Código:

#include <bits/stdc++.h>
#define maxn 1000010
#define maxm 25
using namespace std;
long long ans;
struct Edge{
    
    
	int to, next;
}edge[maxn];
int num, head[maxn], a[maxn], val[25][maxn], n, power[25];

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

void addedge(int x, int y){
    
     edge[++num] = (Edge){
    
    y, head[x]}, head[x] = num; }

int dfs(int u, int d){
    
    
	int s = a[u];
	for (int i = 0; i <= 20; ++i) val[i][(d + a[u]) & (power[i] - 1)] ^= power[i];
	for (int i = 0; i <= 20; ++i) s ^= val[i][d & (power[i] - 1)];
	for (int i = head[u]; i; i = edge[i].next) s ^= dfs(edge[i].to, d + 1);
	for (int i = 0; i <= 20; ++i) s ^= val[i][d & (power[i] - 1)];
	ans += s;
	return s;
}

int main(){
    
    
	n = read();
	for (int i = 1; i <= n; ++i) a[i] = read();
	for (int i = 2; i <= n; ++i) addedge(read(), i);
	power[0] = 1;
	for (int i = 1; i <= 20; ++i) power[i] = power[i - 1] << 1;
	dfs(1, 0);
	printf("%lld\n", ans);
	return 0;
}

Supongo que te gusta

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