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++ 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 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 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# 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 |
<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)