Range Xor Queries
Explicación
Cuando nos encontramos con consultas de rango, las sumas de prefijos deberían venir inmediatamente a la mente. Sin embargo, como tratamos con sumas XOR sobre un rango, tenemos que usar un arreglo de XOR de prefijos en lugar de un arreglo de sumas de prefijos. Para ello, podemos definir como un arreglo tal que . Así, para cada consulta , nuestra respuesta es simplemente .
Demostración
Sabemos que . También sabemos que .
Por lo tanto, como para cualquier :
.
Esto se simplifica a , que es exactamente lo que buscamos.
Implementación
Complejidad temporal:
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 2e5;
int n, q, arr[MAX_N + 1], prefix[MAX_N + 1], a, b;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cin >> n >> q;
// arr and prefix use 1-based indexing
for (int i = 1; i <= n; ++i) { cin >> arr[i]; }
// Build prefix XOR array
prefix[1] = arr[1];
for (int i = 2; i <= n; i++) { prefix[i] = prefix[i - 1] ^ arr[i]; }
while (q--) {
cin >> a >> b;
cout << (prefix[a - 1] ^ prefix[b]) << endl;
}
}import java.io.*;
import java.util.*;
public class RangeXorQueries {
public static void main(String[] args) {
Kattio io = new Kattio();
int n = io.nextInt();
int q = io.nextInt();
// arr and prefix use 1-based indexing
int[] arr = new int[n + 1];
for (int i = 1; i <= n; i++) { arr[i] = io.nextInt(); }
// Build prefix XOR array
int[] prefix = new int[n + 1];
prefix[1] = arr[1];
for (int i = 2; i <= n; i++) { prefix[i] = prefix[i - 1] ^ arr[i]; }
for (int i = 0; i < q; i++) {
int a = io.nextInt();
int b = io.nextInt();
io.println(prefix[a - 1] ^ prefix[b]);
}
io.close();
}
// CodeSnip{Kattio}
}n, q = map(int, input().split())
arr = list(map(int, input().split()))
xor_arr = [0] * (n + 1)
for i in range(1, n + 1):
xor_arr[i] = arr[i - 1] ^ xor_arr[i - 1]
for _ in range(q):
a, b = map(int, input().split())
print(xor_arr[b] ^ xor_arr[a - 1])