XOR of elements in a given range with updates using Fenwick Tree

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

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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 ancestores 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;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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 ancestores 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

chevron_right


Output:

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.

competitive-programming-img




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

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 Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : princi singh