descripción
Pinchame para ver el título (づ  ̄3 ̄) づ ╭❤ ~
solución
XOR y base lineal de máxima correlación
Base lineal:
- Cada número de la secuencia original se puede obtener aplicando XOR a varios números de forma lineal.
- El resultado del OR exclusivo de un número de números en una base lineal no puede ser 0
Si la complejidad temporal del árbol de segmento de línea directa que se fusiona con una base lineal es inaceptable,
desconéctese, considere dividir y conquistar lo
mismo, solo proceda en la división y conquista del intervalo izquierdo o derecho, considere que la consulta cruza el medio medio medio mediom I D del
proceso[l, mid] [l,[ l ,m i d ] La base lineal del sufijo de cada punto en el intervalo,[mid + 1, r] [mid + 1, r][ m i d+1 ,r ] La base lineal del prefijo de cada punto en el intervalo, la
base lineal se puede fusionar violentamente
código
#include <cstdio>
#include <cstring>
#define maxn 500005
int n, Q;
int a[maxn], ql[maxn], qr[maxn], p[maxn];
int left[maxn], right[maxn], ans[maxn];
struct node {
int f[20];
void insert( int x ) {
for( int i = 19;~ i;i -- )
if( ( 1 << i ) & x ) {
if( ! f[i] ) {
f[i] = x; break; }
else x ^= f[i];
}
}
void clear() {
memset( f, 0, sizeof( f ) );
}
}base[maxn];
int merge( node x, node y ) {
//线性基合并
int num = 0;
for( int i = 19;~ i;i -- )
x.insert( y.f[i] );
for( int i = 19;~ i;i -- )
if( ( num ^ x.f[i] ) > num ) num ^= x.f[i];
return num;
}
void solve( int L, int R, int l, int r ) {
if( L > R || l > r ) return;
if( l == r ) {
for( int i = L;i <= R;i ++ )
ans[p[i]] = a[l];
return;
}
int mid = ( l + r ) >> 1, lenl = 0, lenr = 0;
//暴力重构区间[l',r']的线性基
base[mid].clear(); //不要忘记清空了!!
base[mid].insert( a[mid] );
for( int i = mid - 1;i >= l;i -- )
base[i] = base[i + 1], base[i].insert( a[i] );
for( int i = mid + 1;i <= r;i ++ )
base[i] = base[i - 1], base[i].insert( a[i] );
for( int i = L;i <= R;i ++ ) {
int id = p[i];
if( ql[id] <= mid ) {
if( qr[id] <= mid ) //完全在左区间 递归处理
left[++ lenl] = id;
else
ans[id] = merge( base[ql[id]], base[qr[id]] );
}
else //完全在右区间 递归处理
right[++ lenr] = id;
}
for( int i = 1;i <= lenl;i ++ ) p[L + i - 1] = left[i];
for( int i = 1;i <= lenr;i ++ ) p[L + lenl + i - 1] = right[i];
solve( L, L + lenl - 1, l, mid );
solve( L + lenl, L + lenl + lenr - 1, mid + 1, r );
}
int main() {
scanf( "%d", &n );
for( int i = 1;i <= n;i ++ )
scanf( "%d", &a[i] );
scanf( "%d", &Q );
for( int i = 1;i <= Q;i ++ ) {
scanf( "%d %d", &ql[i], &qr[i] );
p[i] = i;
}
solve( 1, Q, 1, n );
for( int i = 1;i <= Q;i ++ )
printf( "%d\n", ans[i] );
return 0;
}