Bits and Pieces
Explicación
Sea la operación OR bit a bit y la operación AND bit a bit.
La respuesta equivale a hallar un tal que y se maximiza para tres índices .
Observemos que se puede buscar por bits, ya que , así que podemos recorrer cada en orden decreciente y comprobar si existe una respuesta para tal que es un superconjunto de . Cuando llegamos a un bit que ya está contenido en , no importa si está en el final porque ya contiene .
En otras palabras, hay que hallar un par tal que y es un superconjunto de . Esto equivale a hallar y tales que , y . Esto se puede hacer con DP de suma sobre subconjuntos (o superconjuntos en este caso) manteniendo y , que guardan los dos más grandes tales que .
Implementación
Complejidad temporal: donde .
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6;
const int B = 21;
const int A = 1 << B;
int main() {
int n;
cin >> n;
vector<int> a(n), f(A, -1), g(A, -1);
for (int i = 0; i < n; i++) {
cin >> a[i];
// el segundo mayor pasa a ser el mayor; el mayor se actualiza a i
f[a[i]] = g[a[i]];
g[a[i]] = i;
}
for (int i = 0; i < B; i++) {
for (int j = 0; j < A; j++) {
if (j & (1 << i)) {
int k = j ^ (1 << i);
// actualizamos el mayor (g[k]) del superconjunto k al subconjunto j
if (f[j] > g[k]) { // caso 1: a la derecha
f[k] = g[k], g[k] = f[j];
} else if (f[j] > f[k]) { // caso 2: en el medio
f[k] = f[j];
}
// actualizamos el segundo mayor (f[k]) del superconjunto k al subconjunto j
if (g[j] > g[k]) { // caso 1: a la derecha
f[k] = g[k], g[k] = g[j];
} else if (g[j] > f[k]) { // caso 2: en el medio
f[k] = g[j];
}
}
}
}
int ans = 0;
for (int i = 0; i < n - 2; i++) {
int c = 0;
for (int j = B - 1; j >= 0; j--) {
/*
* solo consideramos si a[i] no contiene 2^j y
* si el segundo mayor es mayor que i
*/
if ((a[i] & (1 << j)) == 0 && f[c | (1 << j)] > i) { c |= 1 << j; }
}
ans = max(ans, a[i] | c);
}
cout << ans << endl;
}