Given an array A[] of integers and array Q consisting of queries of the following two types:
- (1, L, R) : Return XOR of all elements present between indices L and R.
- (2, I, val) : update A[I] to A[I] XOR val.
The task is to solve each query and print the XOR for every Query of 1st type, using Fenwick Tree.
Examples:
Input: A[] = {2, 1, 1, 3, 2, 3, 4, 5, 6, 7, 8, 9}
Q = {{ 1, 3, 8}, {2, 4, 6}, {1, 3, 8}}
Output :
XOR of elements in range 3 to 8 is 5
XOR of elements in range 3 to 8 is 3
Explanation:
XOR of subarray { 3, 2, 3, 4, 5, 6 } is 5.
After 2nd query arr[4] gets replaced by 4.
Xor of subarray { 3, 4, 3, 4, 5, 6 } is 3.
Input :A[] = {2, 1, 1, 3, 2, 3, 4, 5, 6, 7, 8, 9}
Q = {{1, 0, 9}, {2, 3, 6}, {2, 5, 5}, {2, 8, 1}, {1, 0, 9}}
Output :
XOR of elements in range 0 to 9 is 0
XOR of elements in range 0 to 9 is 2
Approach:
- For the query of type 1, return the Xor of elements in range [1, R] and range[1, L-1] using getXor().
- In getXor(), For i starting from index to all its ancestors till 1, keep calculating XOR with BITree[i]. In order to get ancestor of i-th index in getXor() view, we just need to subtract LSB(least Significant Bit) from i by i = i – i&(-i). Finally return the final XOR value.
- For query of type 2, update A[index] to A[index] ^ val. Update all ranges that include this element in BITree[] by calling updateBIT().
- In updateBIT(), For every i starting from index to all its ancestors up to N, update BITree[i] as BITree[i] ^ val. In order to get ancestor of i-th index in updateBit() view, we just need to add LSB(least Significant Bit) from i by i = i + i&(-i).
Below is the implementation of the above approach:
C++
// C++ Program to find XOR of // elements in given range [L, R]. #include <bits/stdc++.h> using namespace std; // Returns XOR of arr[0..index]. // This function assumes that the // array is preprocessed and partial // XORs of array elements are stored // in BITree[]. int getXOR( int BITree[], int index) { int ans = 0; index += 1; // Traverse ancestors // of BITree[index] while (index > 0) { // XOR current element // of BIT to ans ans ^= BITree[index]; // Update index to that // of the parent node in // getXor() view by // subtracting LSB(Least // Significant Bit) index -= index & (-index); } return ans; } // Updates the Binary Index Tree by // replacing all ancestors of index // by their respective XOR with val void updateBIT( int BITree[], int n, int index, int val) { index = index + 1; // Traverse all ancestors // and XOR with 'val'. while (index <= n) { // XOR 'val' to current // node of BIT BITree[index] ^= val; // Update index to that // of the parent node in // updateBit() view by // adding LSB(Least // Significant Bit) index += index & (-index); } } // Constructs and returns a Binary // Indexed Tree for the given array int * constructBITree( int arr[], int n) { // Create and initialize // the Binary Indexed Tree int * BITree = new int [n + 1]; for ( int i = 1; i <= n; i++) BITree[i] = 0; // Store the actual values in // BITree[] using update() for ( int i = 0; i < n; i++) updateBIT(BITree, n, i, arr[i]); return BITree; } int rangeXor( int BITree[], int l, int r) { return getXOR(BITree, r) ^ getXOR(BITree, l - 1); } // Driver Code int main() { int A[] = { 2, 1, 1, 3, 2, 3, 4, 5, 6, 7, 8, 9 }; int n = sizeof (A) / sizeof (A[0]); vector<vector< int > > q = { { 1, 0, 9 }, { 2, 3, 6 }, { 2, 5, 5 }, { 2, 8, 1 }, { 1, 0, 9 } }; // Create the Binary Indexed Tree int * BITree = constructBITree(A, n); // Solve each query in Q for ( int i = 0; i < q.size(); i++) { int id = q[i][0]; if (id == 1) { int L = q[i][1]; int R = q[i][2]; cout << "XOR of elements " << "in given range is " << rangeXor(BITree, L, R) << "\n" ; } else { int idx = q[i][1]; int val = q[i][2]; A[idx] ^= val; // Update the values of all // ancestors of idx updateBIT(BITree, n, idx, val); } } return 0; } |
Java
// Java Program to find XOR of // elements in given range [L, R]. import java.util.*; class GFG{ // Returns XOR of arr[0..index]. // This function assumes that the // array is preprocessed and partial // XORs of array elements are stored // in BITree[]. static int getXOR( int BITree[], int index) { int ans = 0 ; index += 1 ; // Traverse ancestors // of BITree[index] while (index > 0 ) { // XOR current element // of BIT to ans ans ^= BITree[index]; // Update index to that // of the parent node in // getXor() view by // subtracting LSB(Least // Significant Bit) index -= index & (-index); } return ans; } // Updates the Binary Index Tree by // replacing all ancestors of index // by their respective XOR with val static void updateBIT( int BITree[], int n, int index, int val) { index = index + 1 ; // Traverse all ancestors // and XOR with 'val'. while (index <= n) { // XOR 'val' to current // node of BIT BITree[index] ^= val; // Update index to that // of the parent node in // updateBit() view by // adding LSB(Least // Significant Bit) index += index & (-index); } } // Constructs and returns a Binary // Indexed Tree for the given array static int [] constructBITree( int arr[], int n) { // Create and initialize // the Binary Indexed Tree int []BITree = new int [n + 1 ]; for ( int i = 1 ; i <= n; i++) BITree[i] = 0 ; // Store the actual values in // BITree[] using update() for ( int i = 0 ; i < n; i++) updateBIT(BITree, n, i, arr[i]); return BITree; } static int rangeXor( int BITree[], int l, int r) { return getXOR(BITree, r) ^ getXOR(BITree, l - 1 ); } // Driver Code public static void main(String[] args) { int A[] = { 2 , 1 , 1 , 3 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 }; int n = A.length; int [][]q = { { 1 , 0 , 9 }, { 2 , 3 , 6 }, { 2 , 5 , 5 }, { 2 , 8 , 1 }, { 1 , 0 , 9 } }; // Create the Binary Indexed Tree int []BITree = constructBITree(A, n); // Solve each query in Q for ( int i = 0 ; i < q.length; i++) { int id = q[i][ 0 ]; if (id == 1 ) { int L = q[i][ 1 ]; int R = q[i][ 2 ]; System.out.print( "XOR of elements " + "in given range is " + rangeXor(BITree, L, R) + "\n" ); } else { int idx = q[i][ 1 ]; int val = q[i][ 2 ]; A[idx] ^= val; // Update the values of all // ancestors of idx updateBIT(BITree, n, idx, val); } } } } // This code is contributed by Princi Singh |
Python3
# Python3 program to find XOR of # elements in given range [L, R]. # Returns XOR of arr[0..index]. # This function assumes that the # array is preprocessed and partial # XORs of array elements are stored # in BITree[]. def getXOR(BITree, index): ans = 0 index + = 1 # Traverse ancestors # of BITree[index] while (index > 0 ): # XOR current element # of BIT to ans ans ^ = BITree[index] # Update index to that # of the parent node in # getXor() view by # subtracting LSB(Least # Significant Bit) index - = index & ( - index) return ans # Updates the Binary Index Tree by # replacing all ancestors of index # by their respective XOR with val def updateBIT(BITree, n, index, val): index = index + 1 # Traverse all ancestors # and XOR with 'val'. while (index < = n): # XOR 'val' to current # node of BIT BITree[index] ^ = val # Update index to that # of the parent node in # updateBit() view by # adding LSB(Least # Significant Bit) index + = index & ( - index) # Constructs and returns a Binary # Indexed Tree for the given array def constructBITree(arr, n): # Create and initialize # the Binary Indexed Tree BITree = [ 0 ] * (n + 1 ) # Store the actual values in # BITree[] using update() for i in range (n): updateBIT(BITree, n, i, arr[i]) return BITree def rangeXor(BITree, l, r): return (getXOR(BITree, r) ^ getXOR(BITree, l - 1 )) # Driver Code if __name__ = = "__main__" : A = [ 2 , 1 , 1 , 3 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] n = len (A) q = [ [ 1 , 0 , 9 ], [ 2 , 3 , 6 ], [ 2 , 5 , 5 ], [ 2 , 8 , 1 ], [ 1 , 0 , 9 ] ] # Create the Binary Indexed Tree BITree = constructBITree(A, n) # Solve each query in Q for i in range ( len (q)): id = q[i][ 0 ] if ( id = = 1 ): L = q[i][ 1 ] R = q[i][ 2 ] print ( "XOR of elements in " "given range is " , rangeXor(BITree, L, R)) else : idx = q[i][ 1 ] val = q[i][ 2 ] A[idx] ^ = val # Update the values of all # ancestors of idx updateBIT(BITree, n, idx, val) # This code is contributed by jana_sayantan |
C#
// C# program to find XOR of // elements in given range [L, R]. using System; class GFG{ // Returns XOR of arr[0..index]. // This function assumes that the // array is preprocessed and partial // XORs of array elements are stored // in BITree[]. static int getXOR( int []BITree, int index) { int ans = 0; index += 1; // Traverse ancestors // of BITree[index] while (index > 0) { // XOR current element // of BIT to ans ans ^= BITree[index]; // Update index to that // of the parent node in // getXor() view by // subtracting LSB(Least // Significant Bit) index -= index & (-index); } return ans; } // Updates the Binary Index Tree by // replacing all ancestors of index // by their respective XOR with val static void updateBIT( int []BITree, int n, int index, int val) { index = index + 1; // Traverse all ancestors // and XOR with 'val'. while (index <= n) { // XOR 'val' to current // node of BIT BITree[index] ^= val; // Update index to that // of the parent node in // updateBit() view by // adding LSB(Least // Significant Bit) index += index & (-index); } } // Constructs and returns a Binary // Indexed Tree for the given array static int [] constructBITree( int []arr, int n) { // Create and initialize // the Binary Indexed Tree int []BITree = new int [n + 1]; for ( int i = 1; i <= n; i++) BITree[i] = 0; // Store the actual values in // BITree[] using update() for ( int i = 0; i < n; i++) updateBIT(BITree, n, i, arr[i]); return BITree; } static int rangeXor( int []BITree, int l, int r) { return getXOR(BITree, r) ^ getXOR(BITree, l - 1); } // Driver Code public static void Main(String[] args) { int []A = { 2, 1, 1, 3, 2, 3, 4, 5, 6, 7, 8, 9 }; int n = A.Length; int [,]q = { { 1, 0, 9 }, { 2, 3, 6 }, { 2, 5, 5 }, { 2, 8, 1 }, { 1, 0, 9 } }; // Create the Binary Indexed Tree int []BITree = constructBITree(A, n); // Solve each query in Q for ( int i = 0; i < q.GetLength(0); i++) { int id = q[i, 0]; if (id == 1) { int L = q[i, 1]; int R = q[i, 2]; Console.Write( "XOR of elements " + "in given range is " + rangeXor(BITree, L, R) + "\n" ); } else { int idx = q[i, 1]; int val = q[i, 2]; A[idx] ^= val; // Update the values of // all ancestors of idx updateBIT(BITree, n, idx, val); } } } } // This code is contributed by sapnasingh4991 |
Javascript
<script> // Javascript Program to find XOR of // elements in given range [L, R]. // Returns XOR of arr[0..index]. // This function assumes that the // array is preprocessed and partial // XORs of array elements are stored // in BITree[]. function getXOR(BITree, index) { let ans = 0; index += 1; // Traverse ancestors // of BITree[index] while (index > 0) { // XOR current element // of BIT to ans ans ^= BITree[index]; // Update index to that // of the parent node in // getXor() view by // subtracting LSB(Least // Significant Bit) index -= index & (-index); } return ans; } // Updates the Binary Index Tree by // replacing all ancestors of index // by their respective XOR with val function updateBIT(BITree, n, index, val) { index = index + 1; // Traverse all ancestors // and XOR with 'val'. while (index <= n) { // XOR 'val' to current // node of BIT BITree[index] ^= val; // Update index to that // of the parent node in // updateBit() view by // adding LSB(Least // Significant Bit) index += index & (-index); } } // Constructs and returns a Binary // Indexed Tree for the given array function constructBITree(arr, n) { // Create and initialize // the Binary Indexed Tree let BITree = new Array(n + 1); for (let i = 1; i <= n; i++) BITree[i] = 0; // Store the actual values in // BITree[] using update() for (let i = 0; i < n; i++) updateBIT(BITree, n, i, arr[i]); return BITree; } function rangeXor(BITree, l, r) { return getXOR(BITree, r) ^ getXOR(BITree, l - 1); } // Driver Code let A = [ 2, 1, 1, 3, 2, 3, 4, 5, 6, 7, 8, 9 ]; let n = A.length; let q = [ [ 1, 0, 9 ], [ 2, 3, 6 ], [ 2, 5, 5 ], [ 2, 8, 1 ], [ 1, 0, 9 ] ]; // Create the Binary Indexed Tree let BITree = constructBITree(A, n); // Solve each query in Q for (let i = 0; i < q.length; i++) { let id = q[i][0]; if (id == 1) { let L = q[i][1]; let R = q[i][2]; document.write( "XOR of elements " + "in given range is " + rangeXor(BITree, L, R) + "<br>" ); } else { let idx = q[i][1]; let val = q[i][2]; A[idx] ^= val; // Update the values of all // ancestors of idx updateBIT(BITree, n, idx, val); } } </script> |
XOR of elements in given range is 0 XOR of elements in given range is 2
Time complexity of getXor(): O(log N)
Time complexity of updateBIT(): O(log N)
Overall Time complexity: O(M * log N) where M and N are the number of queries and size of the given array respectively.
Auxiliary Space: O(N)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!