Dada una serie de números de consultas de tamaño N y Q. Cada consulta o rango se puede representar mediante L (LeftIndex) y R (RightIndex). Encuentre la suma XOR de los números que aparecieron un número par de veces en el rango dado.
Requisito previo: Consultas por número de números distintos en un rango dado. | Árbol de segmentos para consultas de rango
Ejemplos:
Input : arr[] = { 1, 2, 1, 3, 3, 2, 3 } Q = 5 L = 3, R = 6 L = 3, R = 4 L = 0, R = 2 L = 0, R = 6 L = 0, R = 4 Output : 0 3 1 3 2
Explicación del ejemplo anterior:
en la Consulta 1, no hay números que aparezcan un número par de veces.
Por lo tanto, la suma XOR es 0.
En la Consulta 2, {3} apareció un número par de veces. XOR-sum es 3.
En la Consulta 3, {1} apareció un número par de veces. XOR-sum es 1.
En la Consulta 4, {1, 2} apareció un número par de veces. XOR-sum es 1 x o 2 = 3.
En la Consulta 5, {1, 3} apareció un número par de veces. La suma XOR es 1 x o 3 = 2. Los árboles de
segmentos o los árboles indexados binarios se pueden usar para resolver este problema de manera eficiente.
Enfoque:
en primer lugar, es fácil notar que la respuesta para la consulta es la suma XOR de todos los elementos en el rango de consulta xor-ed con la suma XOR de distintoselementos en el rango de consulta (ya que tomar XOR de un elemento consigo mismo da como resultado un valor nulo). Encuentre la suma XOR de todos los números en el rango de consulta usando sumas XOR de prefijo.
Para encontrar la suma XOR de elementos distintos en el rango: Número de elementos distintos en un subarreglo de rango dado .
Ahora, volviendo a nuestro problema principal, simplemente cambie la asignación BIT[i] = 1 a BIT[i] = arr i y cuente la suma XOR en lugar de la suma.
A continuación se muestra la implementación utilizando árboles indexados binarios en CPP
CPP
// CPP Program to Find the XOR-sum // of elements that appeared even // number of times within a range #include <bits/stdc++.h> using namespace std; /* structure to store queries L --> Left Bound of Query R --> Right Bound of Query idx --> Query Number */ struct que { int L, R, idx; }; // cmp function to sort queries // according to R bool cmp(que a, que b) { if (a.R != b.R) return a.R < b.R; else return a.L < b.L; } /* N --> Number of elements present in input array. BIT[0..N] --> Array that represents Binary Indexed Tree*/ // Returns XOR-sum of arr[0..index]. This // function assumes that the array is // preprocessed and partial sums of array // elements are stored in BIT[]. int getSum(int BIT[], int index) { // Initialize result int xorSum = 0; // index in BITree[] is 1 more than // the index in arr[] index = index + 1; // Traverse ancestors of BIT[index] while (index > 0) { // Take XOR of current element // of BIT to xorSum xorSum ^= BIT[index]; // Move index to parent node // in getSum View index -= index & (-index); } return xorSum; } // Updates a node in Binary Index Tree // (BIT) at given index in BIT. The // given value 'val' is xored to BIT[i] // and all of its ancestors in tree. void updateBIT(int BIT[], int N, int index, int val) { // index in BITree[] is 1 more than // the index in arr[] index = index + 1; // Traverse all ancestors and // take xor with 'val' while (index <= N) { // Take xor with 'val' to // current node of BIT BIT[index] ^= val; // Update index to that of // parent in update View index += index & (-index); } } // Constructs and returns a Binary Indexed // Tree for given array of size N. int* constructBITree(int arr[], int N) { // Create and initialize BITree[] as 0 int* BIT = new int[N + 1]; for (int i = 1; i <= N; i++) BIT[i] = 0; return BIT; } // Function to answer the Queries void answeringQueries(int arr[], int N, que queries[], int Q, int BIT[]) { // Creating an array to calculate // prefix XOR sums int* prefixXOR = new int[N + 1]; // map for coordinate compression // as numbers can be very large but we // have limited space map<int, int> mp; for (int i = 0; i < N; i++) { // If A[i] has not appeared yet if (!mp[arr[i]]) mp[arr[i]] = i; // calculate prefixXOR sums if (i == 0) prefixXOR[i] = arr[i]; else prefixXOR[i] = prefixXOR[i - 1] ^ arr[i]; } // Creating an array to store the // last occurrence of arr[i] int lastOcc[1000001]; memset(lastOcc, -1, sizeof(lastOcc)); // sort the queries according to comparator sort(queries, queries + Q, cmp); // answer for each query int res[Q]; // Query Counter int j = 0; for (int i = 0; i < Q; i++) { while (j <= queries[i].R) { // If last visit is not -1 update // arr[j] to set null by taking // xor with itself at the idx // equal lastOcc[mp[arr[j]]] if (lastOcc[mp[arr[j]]] != -1) updateBIT(BIT, N, lastOcc[mp[arr[j]]], arr[j]); // Setting lastOcc[mp[arr[j]]] as j and // updating the BIT array accordingly updateBIT(BIT, N, j, arr[j]); lastOcc[mp[arr[j]]] = j; j++; } // get the XOR-sum of all elements within // range using precomputed prefix XORsums int allXOR = prefixXOR[queries[i].R] ^ prefixXOR[queries[i].L - 1]; // get the XOR-sum of distinct elements // within range using BIT query function int distinctXOR = getSum(BIT, queries[i].R) ^ getSum(BIT, queries[i].L - 1); // store the final answer at the numbered query res[queries[i].idx] = allXOR ^ distinctXOR; } // Output the result for (int i = 0; i < Q; i++) cout << res[i] << endl; } // Driver program to test above functions int main() { int arr[] = { 1, 2, 1, 3, 3, 2, 3 }; int N = sizeof(arr) / sizeof(arr[0]); int* BIT = constructBITree(arr, N); // structure of array for queries que queries[5]; // Initializing values (L, R, idx) to queries queries[0].L = 3; queries[0].R = 6, queries[0].idx = 0; queries[1].L = 3; queries[1].R = 4, queries[1].idx = 1; queries[2].L = 0; queries[2].R = 2, queries[2].idx = 2; queries[3].L = 0; queries[3].R = 6, queries[3].idx = 3; queries[4].L = 0; queries[4].R = 4, queries[4].idx = 4; int Q = sizeof(queries) / sizeof(queries[0]); // answer Queries answeringQueries(arr, N, queries, Q, BIT); return 0; }
0 3 1 3 2
Complejidad de tiempo: O(Q * Log(N)), donde N es el tamaño de la array, Q es el número total de consultas.
Complejidad espacial : O (N) donde N es el tamaño de la array
Publicación traducida automáticamente
Artículo escrito por Nishant Tanwar y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA