Secuencias XOR y Conteo de Caminos en Árboles

Suma de Subarreglos mediante Operaciones XOR

Dado un arreglo de tamaño \(n\), se requiere calcular la suma de todas las sumas XOR para cada subarreglo posible. El problema considera múltiples casos de prueba con diferentes tamaños de entrada.

Análisis de Solución

Optimización por bits: Se utiliza la propiedad de bits independientes para procesar cada componente binario por separado. La técnica aprovecha:

  • Precálculo de XOR acumulativo para acceso rápido a rangos
  • Conteo dinámico de pares que activan bits específicos

Implementación Eficiente

#include <iostream>
#include <vector>
using namespace std;

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  
  int casos;
  cin >> casos;
  
  while (casos--) {
    int tam;
    cin >> tam;
    vector<long> arr(tam);
    for (int i = 0; i < tam; ++i) cin >> arr[i];
    
    vector<long> acum(tam + 1);
    for (int i = 0; i < tam; ++i)
      acum[i + 1] = acum[i] ^ arr[i];
    
    unsigned long long total = 0;
    for (int bit = 0; bit < 31; ++bit) {
      int contarCeros = 1, contarUnos = 0;
      unsigned long sumaParcial = 0;
      
      for (int i = 1; i <= tam; ++i) {
        if (acum[i] >> bit & 1) {
          sumaParcial += contarCeros;
          contarUnos++;
        }
        else {
          sumaParcial += contarUnos;
          contarCeros++;
        }
      }
      total += sumaParcial * (1LL << bit);
    }
    cout << total << '\n';
  }
  
  return 0;
}

Rutas de Longitud Par en Estructuras Arbóreas

Dado un árbol no dirigido, se calcula el número de caminos que contienen exactamente un número par de nodos entre nodos arbitrarios.

Técnica de Resolución

DP en árboles: Se implementa un recorriod DFS que almacena estados según paridad de distancias:

  • [0]: Recuento de rutas con distancia par
  • [1]: Recuento de rutas con distancia impar

Se actualiza dinámicamente durante recorrido

Solución Óptima

#include <iostraem>
#include <vector>
using namespace std;

int main() {
  int totalNodos;
  cin >> totalNodos;
  vector<vector<int>> conexiones(totalNodos);
  
  for (int i = 1; i < totalNodos; ++i) {
    int u, v;
    cin >> u >> v;
    u--; v--;
    conexiones[u].push_back(v);
    conexiones[v].push_back(u);
  }
  
  vector<vector<int>> estados(totalNodos, vector<int>(2, 0));
  
  function<void(int, int)> dfs = [&](int actual, int padre) {
    for (int hijo : conexiones[actual]) {
      if (hijo == padre) continue;
      dfs(hijo, actual);
      estados[actual][0] += estados[hijo][1];
      estados[actual][1] += estados[hijo][0] + 1;
    }
  };
  
  dfs(0, -1);
  long long resultado = (long long)(estados[0][0] + 1) * estados[0][1];
  cout << resultado;
  
  return 0;
}

Etiquetas: XOR prefijos bitwise árboles DFS

Publicado el 9-29 08:05