Given an array of numbers of size N and Q queries. Each query or a range can be represented by L (LeftIndex) and R(RightIndex). Find the XOR-sum of the numbers that appeared even number of times in the given range.

**Prerequisite : **Queries for number of distinct numbers in given range. | Segment Tree for range query

Examples :

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

**Explanation of above example: **

In Query 1, there are no numbers which appeared even number of times.

Hence the XOR-sum is 0.

In Query 2, {3} appeared even number of times. XOR-sum is 3.

In Query 3, {1} appeared even number of times. XOR-sum is 1.

In Query 4, {1, 2} appeared even number of times. XOR-sum is 1 xor 2 = 3.

In Query 5, {1, 3} appeared even number of times. XOR-sum is 1 xor 3 = 2.

Segment Trees or Binary Indexed Trees can be used to solve this problem efficiently.

**Approach : **

Firstly, it is easy to note that the answer for the query is the XOR-sum of **all** elements in the query range xor-ed with XOR-sum of **distinct** elements in the query range (since taking XOR of an element with itself results into a null value). Find the XOR-sum of all numbers in query range using prefix XOR-sums.

**To find the XOR-sum of distinct elements in range :** Number of distinct elements in a subarray of given range.

Now, returning back to our main problem, just change the assignment BIT[i] = 1 to BIT[i] = arr_{i} and count the XOR-sum instead of sum.

**Below is the implementation using Binary Indexed Trees in 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) { // Iniialize 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 occurence 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]; // Intializing 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; }

**Output:**

0 3 1 3 2

**Time Complexity:** O(Q * Log(N)), where N is the size of array, Q is the total number of queries.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.