Open In App

Count of subarrays in range [L, R] having XOR + 1 equal to XOR (XOR) 1 for M queries

Given an array, arr[] of N positive integers and M queries which consist of two integers [Li, Ri] where 1 ? Li ? Ri ? N. For each query, find the number of subarrays in range [Li, Ri] for which (X+1)=(X?1) where X denotes the xor of a subarray.

Input: arr[]= {1, 2, 9, 8, 7}, queries[] = {{1, 5}, {3, 4}}
Output: 6 1
Explanation: 
Query 1: L=1, R=5: subarrays [1, 3], [1, 4], [2, 2], [2, 5], [3, 5], [4, 4]
Query 2: L=3, R=4: subarray [4, 4]



Input: arr[] = {1, 2, 2, 4, 5}, queries[] = {{2, 4}, {3, 5}}
Output: 6 3

Naive approach: For each query, select the given range [Li, Ri] and for each subarray check if it satisfies the given condition. 
Time complexity: O(N3 * M)



Efficient approach: In the above problem, the following observations can be made:

Below is the implementation of the above approach:




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
vector<int> countXorSubarr(
    vector<int> arr,
    vector<vector<int> > queries,
    int n, int m)
{
 
    // As queries are in 1-based indexing,
    // add one dummy entry in beginning
    // of arr to make it 1-indexed
    arr.insert(arr.begin(), 0);
 
    // sum[] will contain parity
    // of prefix sum till index i
    // count[] will contain
    // number of 0s in sum[]
    int count[n + 1], sum[n + 1];
    count[0] = sum[0] = 0;
 
    for (int i = 1; i <= n; i++) {
 
        // Take the parity of current sum
        sum[i] = (sum[i - 1] + arr[i]) % 2;
        count[i] = count[i - 1];
 
        // If current parity is even,
        // increase the count
        if (sum[i] % 2 == 0)
            count[i]++;
    }
 
    // Array to hold the answer of 'm' queries
    vector<int> ans;
 
    // Iterate through queries and use handshake
    // lemma to count even sum subarrays
    // ( Note that an even sum can
    // be formed by two even or two odd )
    for (vector<int> qu : queries) {
        int L = qu[0], R = qu[1];
 
        // Find count of even and
        // odd sums in range [L, R]
        int even = count[R] - count[L - 1];
        int odd = (R - L + 1) - even;
 
        // If prefix sum at L-1 is odd,
        // then we need to swap
        // our counts of odd and even
        if (sum[L - 1] == 1)
            swap(even, odd);
 
        // Taking no element is also
        // considered an even sum
        // so even will be increased by 1
        // (This is the condition when
        // a prefix of even sum is taken)
        even++;
 
        // Find number of ways to
        // select two even's or two odd's
        int subCount = (even * (even - 1)) / 2
                       + (odd * (odd - 1)) / 2;
 
        ans.push_back(subCount);
    }
 
    return ans;
}
 
// Driver code
int main()
{
    int n = 5;
    vector<int> arr = { 1, 2, 9, 8, 7 };
    int m = 2;
    vector<vector<int> > queries
        = { { 1, 5 }, { 3, 4 } };
 
    // Function call and print answer
    vector<int> ans
        = countXorSubarr(arr, queries, n, m);
    for (int x : ans)
        cout << x << " ";
    cout << endl;
 
    return 0;
}




// Java program for the above approach
import java.util.ArrayList;
 
class GFG
{
 
    public static ArrayList<Integer> countXorSubarr(int[] arr, int[][] queries, int n, int m) {
 
        // As queries are in 1-based indexing,
        // add one dummy entry in beginning
        // of arr to make it 1-indexed
        // arr.insert(arr.begin(), 0);
        int[] temp_arr = new int[arr.length + 1];
        temp_arr[0] = 0;
        for (int i = 1; i < temp_arr.length; i++) {
            temp_arr[i] = arr[i - 1];
        }
        arr = temp_arr.clone();
 
        // sum[] will contain parity
        // of prefix sum till index i
        // count[] will contain
        // number of 0s in sum[]
        int[] count = new int[n + 1];
        int[] sum = new int[n + 1];
        count[0] = sum[0] = 0;
 
        for (int i = 1; i <= n; i++) {
 
            // Take the parity of current sum
            sum[i] = (sum[i - 1] + arr[i]) % 2;
            count[i] = count[i - 1];
 
            // If current parity is even,
            // increase the count
            if (sum[i] % 2 == 0)
                count[i]++;
        }
 
        // Array to hold the answer of 'm' queries
        ArrayList<Integer> ans = new ArrayList<Integer>();
 
        // Iterate through queries and use handshake
        // lemma to count even sum subarrays
        // ( Note that an even sum can
        // be formed by two even or two odd )
        for (int[] qu : queries) {
            int L = qu[0], R = qu[1];
 
            // Find count of even and
            // odd sums in range [L, R]
            int even = count[R] - count[L - 1];
            int odd = (R - L + 1) - even;
 
            // If prefix sum at L-1 is odd,
            // then we need to swap
            // our counts of odd and even
            if (sum[L - 1] == 1) {
                int temp = even;
                even = odd;
                odd = temp;
            }
 
            // Taking no element is also
            // considered an even sum
            // so even will be increased by 1
            // (This is the condition when
            // a prefix of even sum is taken)
            even++;
 
            // Find number of ways to
            // select two even's or two odd's
            int subCount = (even * (even - 1)) / 2 + (odd * (odd - 1)) / 2;
 
            ans.add(subCount);
        }
 
        return ans;
    }
 
    // Driver code
    public static void main(String args[])
    {
        int n = 5;
        int[] arr = { 1, 2, 9, 8, 7 };
        int m = 2;
        int[][] queries = { { 1, 5 }, { 3, 4 } };
 
        // Function call and print answer
        ArrayList<Integer> ans = countXorSubarr(arr, queries, n, m);
        for (int x : ans)
            System.out.print(x + " ");
        System.out.println("");
 
    }
}
 
// This code is contributed by saurabh_jaiswal.




# python program for the above approach
import math
def countXorSubarr(arr, queries, n, m):
 
        # As queries are in 1-based indexing,
        # add one dummy entry in beginning
        # of arr to make it 1-indexed
    arr.insert(0, 0)
 
    # sum[] will contain parity
    # of prefix sum till index i
    # count[] will contain
    # number of 0s in sum[]
    count = [0 for _ in range(n + 1)]
    sum = [0 for _ in range(n + 1)]
 
    for i in range(1, n+1):
 
                # Take the parity of current sum
        sum[i] = (sum[i - 1] + arr[i]) % 2
        count[i] = count[i - 1]
 
        # If current parity is even,
        # increase the count
        if (sum[i] % 2 == 0):
            count[i] += 1
 
        # Array to hold the answer of 'm' queries
    ans = []
 
    # Iterate through queries and use handshake
    # lemma to count even sum subarrays
    # ( Note that an even sum can
    # be formed by two even or two odd )
    for qu in queries:
 
        L = qu[0]
        R = qu[1]
 
        # Find count of even and
        # odd sums in range [L, R]
        even = count[R] - count[L - 1]
        odd = (R - L + 1) - even
 
        # If prefix sum at L-1 is odd,
        # then we need to swap
        # our counts of odd and even
        if (sum[L - 1] == 1):
            temp = even
            even = odd
            odd = temp
 
            # Taking no element is also
            # considered an even sum
            # so even will be increased by 1
            # (This is the condition when
            # a prefix of even sum is taken)
        even += 1
 
        # Find number of ways to
        # select two even's or two odd's
        subCount = (even * (even - 1)) // 2 + (odd * (odd - 1)) // 2
        ans.append(subCount)
    return ans
 
# Driver code
if __name__ == "__main__":
 
    n = 5
    arr = [1, 2, 9, 8, 7]
    m = 2
    queries = [[1, 5], [3, 4]]
 
    # Function call and print answer
    ans = countXorSubarr(arr, queries, n, m)
    for x in ans:
        print(x, end=" ")
 
    # This code is contributed by rakeshsahni




// C# program for the above approach
using System;
using System.Collections.Generic;
 
public class GFG
{
 
    public static List<int> countXorSubarr(int[] arr, int[,] queries, int n, int m)
    {
 
        // As queries are in 1-based indexing,
        // add one dummy entry in beginning
        // of arr to make it 1-indexed
        // arr.insert(arr.begin(), 0);
        int[] temp_arr = new int[arr.Length + 1];
        temp_arr[0] = 0;
        for (int i = 1; i < temp_arr.Length; i++) {
            temp_arr[i] = arr[i - 1];
        }
        arr = temp_arr;
 
        // sum[] will contain parity
        // of prefix sum till index i
        // []count will contain
        // number of 0s in sum[]
        int[] count = new int[n + 1];
        int[] sum = new int[n + 1];
        count[0] = sum[0] = 0;
 
        for (int i = 1; i <= n; i++) {
 
            // Take the parity of current sum
            sum[i] = (sum[i - 1] + arr[i]) % 2;
            count[i] = count[i - 1];
 
            // If current parity is even,
            // increase the count
            if (sum[i] % 2 == 0)
                count[i]++;
        }
 
        // Array to hold the answer of 'm' queries
        List<int> ans = new List<int>();
 
        // Iterate through queries and use handshake
        // lemma to count even sum subarrays
        // ( Note that an even sum can
        // be formed by two even or two odd )
         
        for(int i = 0; i < queries.GetLength(0); i++)
        {
            int L = queries[i,0], R = queries[i,1];
 
            // Find count of even and
            // odd sums in range [L, R]
            int even = count[R] - count[L - 1];
            int odd = (R - L + 1) - even;
 
            // If prefix sum at L-1 is odd,
            // then we need to swap
            // our counts of odd and even
            if (sum[L - 1] == 1) {
                int temp = even;
                even = odd;
                odd = temp;
            }
 
            // Taking no element is also
            // considered an even sum
            // so even will be increased by 1
            // (This is the condition when
            // a prefix of even sum is taken)
            even++;
 
            // Find number of ways to
            // select two even's or two odd's
            int subCount = (even * (even - 1)) / 2 + (odd * (odd - 1)) / 2;
 
            ans.Add(subCount);
         
        }
        return ans;
    }
      public static int[] GetRow(int[,] matrix, int row)
      {
        var rowLength = matrix.GetLength(1);
        var rowVector = new int[rowLength];
 
        for (var i = 0; i < rowLength; i++)
          rowVector[i] = matrix[row, i];
 
        return rowVector;
      }
   
    // Driver code
    public static void Main(String []args)
    {
        int n = 5;
        int[] arr = { 1, 2, 9, 8, 7 };
        int m = 2;
        int[,] queries = { { 1, 5 }, { 3, 4 } };
 
        // Function call and print answer
        List<int> ans = countXorSubarr(arr, queries, n, m);
        foreach (int x in ans)
            Console.Write(x + " ");
        Console.WriteLine("");
 
    }
}
 
// This code contributed by shikhasingrajput




<script>
       // JavaScript Program to implement
       // the above approach
       function countXorSubarr(arr, queries, n, m)
       {
 
           // sum[] will contain parity
           // of prefix sum till index i
           // count[] will contain
           // number of 0s in sum[]
           let count = new Array(n + 1), sum = new Array(n + 1);
           count[0] = sum[0] = 0;
 
           for (let i = 1; i <= n; i++) {
 
               // Take the parity of current sum
               sum[i] = (sum[i - 1] + arr[i - 1]) % 2;
               count[i] = count[i - 1];
 
               // If current parity is even,
               // increase the count
               if (sum[i] % 2 == 0)
                   count[i]++;
           }
 
           // Array to hold the answer of 'm' queries
           let ans = [];
 
           // Iterate through queries and use handshake
           // lemma to count even sum subarrays
           // ( Note that an even sum can
           // be formed by two even or two odd )
           for (let qu of queries) {
               let L = qu[0], R = qu[1];
 
               // Find count of even and
               // odd sums in range [L, R]
               let even = count[R] - count[L - 1];
               let odd = (R - L + 1) - even;
 
               // If prefix sum at L-1 is odd,
               // then we need to swap
               // our counts of odd and even
               if (sum[L - 1] == 1) {
                   temp = even
                   even = odd
                   odd = temp
               }
 
               // Taking no element is also
               // considered an even sum
               // so even will be increased by 1
               // (This is the condition when
               // a prefix of even sum is taken)
               even++;
 
               // Find number of ways to
               // select two even's or two odd's
               let subCount = (even * (even - 1)) / 2
                   + (odd * (odd - 1)) / 2;
 
               ans.push(subCount);
           }
 
           return ans;
       }
 
       // Driver code
       let n = 5;
       let arr = [1, 2, 9, 8, 7];
       let m = 2;
       let queries
           = [[1, 5], [3, 4]];
 
       // Function call and print answer
       let ans
           = countXorSubarr(arr, queries, n, m);
       for (let x of ans)
           document.write(x + " ");
 
   // This code is contributed by Potta Lokesh
   </script>

Output
6 1 

Time Complexity: O(N+M)
Auxiliary Space: O(N+M)


Article Tags :