Open In App

Range Queries to count the number of even parity values with updates

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Given an array arr[] of N integers, the task is to perform the following two queries: 

  • query(L, R): Print the number of Even Parity numbers in the subarray from L to R.
  • update(i, x): Update the array element reference by index i to x.

Examples:  

Input: arr[] = {18, 15, 8, 9, 14, 5} 
Query 1: query(L = 0, R = 4) 
Query 2: update(i = 3, x = 11) 
Query 3: query(L = 0, R = 4) 
Output: 


Explanation: 
Query 1: Subarray is {18, 15, 8, 9, 14} 
Binary Representation of these elements – 
18 => 10010, Parity = 2 
15 => 1111, Parity = 4 
8 => 1000, Parity = 1 
9 => 1001, Parity = 2 
14 => 1110, Parity = 3 
Subarray[0-4] have 3 elements with even parity. 
Query 2: Update arr[3] = 11 
Updated array, {18, 15, 8, 11, 14, 5} 
Query 3: Subarray is {18, 15, 8, 11, 14} 
Binary Representation of these elements – 
18 => 10010, Parity = 2 
15 => 1111, Parity = 4 
8 => 1000, Parity = 1 
11 => 1011, Parity = 3 
14 => 1110, Parity = 3 
Subarray[0-4] have 2 elements with even parity. 
 

Approach: The idea is to use segment tree to query the count of the even parity elements in a array range and update simultaneously.
We can find the parity for the current value by iterating through each bit of the binary representation of the number and counting the number of set bits. Then check if the parity is even or not. If it has even parity the set it to 1 else to 0.

Building the segment tree:  

  • Leaf nodes of the segment tree is represented as either 0 (if it is odd parity number) or 1 (if it is even parity number).
  • The internal nodes of the segment tree equal to the sum of its child nodes, thus a node represent the total Even Parity numbers in the range from L to R with range [L, R] falling under this node and the sub-tree underneath it.

Handling Queries:  

  • Query(L, R): Whenever we receive a query from start to end, we can query the segment tree for the sum of nodes in the range from start to end, which in turn represents the number of Even Parity numbers in the range start to end.
  • Update(i, x): To perform a update query to update the value at index i to x, we check for the following cases: 
    • Case 1: If previous value and new value both are Even Parity numbers 
      Count of Even Parity numbers in the subarray does not change so we just update array and do not modify the segment tree
    • Case 2: If previous value and new value both are not Even Parity numbers 
      Count of Even Parity numbers in the subarray does not change so we just update array and do not modify the segment tree
    • Case 3: If previous value is a Even Parity number but new value is not a Even Parity number 
      Count of Even Parity numbers in the subarray decreases so we update array and add -1 to every range. The index i which is to be updated is a part of in the segment tree
    • Case 4: If previous value is not a Even Parity number but new value is a Even Parity number 
      Count of Even Parity numbers in the subarray increases so we update array and add 1 to every range. The index i which is to be updated is a part of in the segment tree

Below is the implementation of the above approach: 

C++




// C++ implementation to find
// number of Even Parity numbers
// in a subarray and performing updates
 
#include <bits/stdc++.h>
using namespace std;
 
#define MAX 1000
 
// Function that returns true if count
// of set bits in x is even
bool isEvenParity(int x)
{
    // parity will store the
    // count of set bits
    int parity = 0;
    while (x != 0) {
        if (x & 1)
            parity++;
        x = x >> 1;
    }
 
    if (parity % 2 == 0)
        return true;
    else
        return false;
}
 
// A utility function to get
// the middle index
int getMid(int s, int e)
{
    return s + (e - s) / 2;
}
 
// Recursive function to get the number
// of Even Parity numbers in a given range
int queryEvenParityUtil(
    int* segmentTree, int segmentStart,
    int segmentEnd, int queryStart,
    int queryEnd, int index)
{
    // If segment of this node is a part
    // of given range, then return
    // the number of Even Parity numbers
    // in the segment
    if (queryStart <= segmentStart
        && queryEnd >= segmentEnd)
        return segmentTree[index];
 
    // If segment of this node
    // is outside the given range
    if (segmentEnd < queryStart
        || segmentStart > queryEnd)
        return 0;
 
    // If a part of this segment
    // overlaps with the given range
    int mid = getMid(segmentStart, segmentEnd);
    return queryEvenParityUtil(
               segmentTree, segmentStart, mid,
               queryStart, queryEnd, 2 * index + 1)
           + queryEvenParityUtil(
                 segmentTree, mid + 1, segmentEnd,
                 queryStart, queryEnd, 2 * index + 2);
}
 
// Recursive function to update
// the nodes which have the given
// index in their range
void updateValueUtil(
    int* segmentTree, int segmentStart,
    int segmentEnd, int i, int diff, int si)
{
    // Base Case:
    if (i < segmentStart || i > segmentEnd)
        return;
 
    // If the input index is in range
    // of this node, then update the value
    // of the node and its children
    segmentTree[si] = segmentTree[si] + diff;
    if (segmentEnd != segmentStart) {
 
        int mid = getMid(
            segmentStart, segmentEnd);
        updateValueUtil(
            segmentTree, segmentStart,
            mid, i, diff, 2 * si + 1);
        updateValueUtil(
            segmentTree, mid + 1, segmentEnd,
            i, diff, 2 * si + 2);
    }
}
 
// Function to update a value in the
// input array and segment tree
void updateValue(int arr[], int* segmentTree,
                 int n, int i, int new_val)
{
    // Check for erroneous input index
    if (i < 0 || i > n - 1) {
        printf("Invalid Input");
        return;
    }
 
    int diff, oldValue;
 
    oldValue = arr[i];
 
    // Update the value in array
    arr[i] = new_val;
 
    // Case 1: Old and new values
    // both are Even Parity numbers
    if (isEvenParity(oldValue)
        && isEvenParity(new_val))
        return;
 
    // Case 2: Old and new values
    // both not Even Parity numbers
    if (!isEvenParity(oldValue)
        && !isEvenParity(new_val))
        return;
 
    // Case 3: Old value was Even Parity,
    // new value is non Even Parity
    if (isEvenParity(oldValue)
        && !isEvenParity(new_val)) {
        diff = -1;
    }
 
    // Case 4: Old value was non Even Parity,
    // new_val is Even Parity
    if (!isEvenParity(oldValue)
        && !isEvenParity(new_val)) {
        diff = 1;
    }
 
    // Update the values of
    // nodes in segment tree
    updateValueUtil(segmentTree, 0,
                    n - 1, i, diff, 0);
}
 
// Return number of Even Parity numbers
void queryEvenParity(int* segmentTree,
                     int n, int queryStart,
                     int queryEnd)
{
    int EvenParityInRange
        = queryEvenParityUtil(
            segmentTree, 0, n - 1,
            queryStart, queryEnd, 0);
 
    cout << EvenParityInRange << "\n";
}
 
// Recursive function that constructs
// Segment Tree for the given array
int constructSTUtil(int arr[],
                    int segmentStart,
                    int segmentEnd,
                    int* segmentTree,
                    int si)
{
    // If there is one element in array,
    // check if it is Even Parity number
    // then store 1 in the segment tree
    // else store 0 and return
    if (segmentStart == segmentEnd) {
 
        // if arr[segmentStart] is
        // Even Parity number
        if (isEvenParity(arr[segmentStart]))
            segmentTree[si] = 1;
        else
            segmentTree[si] = 0;
 
        return segmentTree[si];
    }
 
    // If there are more than one elements,
    // then recur for left and right subtrees
    // and store the sum of the
    // two values in this node
    int mid = getMid(segmentStart,
                     segmentEnd);
    segmentTree[si]
        = constructSTUtil(
              arr, segmentStart, mid,
              segmentTree, si * 2 + 1)
          + constructSTUtil(
                arr, mid + 1, segmentEnd,
                segmentTree, si * 2 + 2);
    return segmentTree[si];
}
 
// Function to construct a segment
// tree from given array
int* constructST(int arr[], int n)
{
    // Height of segment tree
    int x = (int)(ceil(log2(n)));
 
    // Maximum size of segment tree
    int max_size = 2 * (int)pow(2, x) - 1;
 
    int* segmentTree = new int[max_size];
 
    // Fill the allocated memory st
    constructSTUtil(arr, 0, n - 1,
                    segmentTree, 0);
 
    // Return the constructed segment tree
    return segmentTree;
}
 
// Driver Code
int main()
{
 
    int arr[] = { 18, 15, 8, 9, 14, 5 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // Build segment tree from given array
    int* segmentTree = constructST(arr, n);
 
    // Query 1: Query(start = 0, end = 4)
    int start = 0;
    int end = 4;
    queryEvenParity(segmentTree, n, start, end);
 
    // Query 2: Update(i = 3, x = 11),
    // i.e Update a[i] to x
    int i = 3;
    int x = 11;
    updateValue(arr, segmentTree, n, i, x);
 
    // Query 3: Query(start = 0, end = 4)
    start = 0;
    end = 4;
    queryEvenParity(
        segmentTree, n, start, end);
 
    return 0;
}


Java




/*package whatever //do not write package name here */
import java.util.*;
public class GFG {
 
  public static int MAX = 1000;
 
  // Function that returns true if count
  // of set bits in x is even
  static boolean isEvenParity(int x)
  {
 
    // parity will store the
    // count of set bits
    int parity = 0;
 
    while (x != 0) {
      if ((x & 1) != 0)
        parity++;
 
      x = x >> 1;
    }
 
    if (parity % 2 == 0)
      return true;
    else
      return false;
  }
 
  // A utility function to get
  // the middle index
  static int getMid(int s, int e)
  {
    return s + (e - s) / 2;
  }
 
  // Recursive function to get the number
  // of Even Parity numbers in a given range
  static int queryEvenParityUtil(int[] segmentTree,
                                 int segmentStart,
                                 int segmentEnd,
                                 int queryStart,
                                 int queryEnd, int index)
  {
 
    // If segment of this node is a part
    // of given range, then return
    // the number of Even Parity numbers
    // in the segment
    if (queryStart <= segmentStart
        && queryEnd >= segmentEnd)
      return segmentTree[index];
 
    // If segment of this node
    // is outside the given range
    if (segmentEnd < queryStart
        || segmentStart > queryEnd)
      return 0;
 
    // If a part of this segment
    // overlaps with the given range
    int mid = getMid(segmentStart, segmentEnd);
    return queryEvenParityUtil(
      segmentTree, segmentStart, mid,
      queryStart, queryEnd, 2 * index + 1)
      + queryEvenParityUtil(segmentTree, mid + 1,
                            segmentEnd, queryStart,
                            queryEnd, 2 * index + 2);
  }
 
  // Recursive function to update
  // the nodes which have the given
  // index in their range
  static void updateValueUtil(int[] segmentTree,
                              int segmentStart,
                              int segmentEnd, int i,
                              int diff, int si)
  {
 
    // Base Case:
    if (i < segmentStart || i > segmentEnd)
      return;
 
    // If the input index is in range
    // of this node, then update the value
    // of the node and its children
    segmentTree[si] = segmentTree[si] + diff;
 
    if (segmentEnd != segmentStart) {
      int mid = getMid(segmentStart, segmentEnd);
      updateValueUtil(segmentTree, segmentStart, mid,
                      i, diff, 2 * si + 1);
      updateValueUtil(segmentTree, mid + 1,
                      segmentEnd, i, diff,
                      2 * si + 2);
    }
  }
 
  // Function to update a value in the
  // input array and segment tree
  static void updateValue(int[] arr, int[] segmentTree,
                          int n, int i, int new_val)
  {
 
    // Check for erroneous input index
    if (i < 0 || i > n - 1) {
      System.out.println("Invalid Input");
      return;
    }
 
    int diff = 0, oldValue = 0;
 
    oldValue = arr[i];
 
    // Update the value in array
    arr[i] = new_val;
 
    // Case 1: Old and new values
    // both are Even Parity numbers
    if (isEvenParity(oldValue) && isEvenParity(new_val))
      return;
 
    // Case 2: Old and new values
    // both not Even Parity numbers
    if (!isEvenParity(oldValue)
        && !isEvenParity(new_val))
      return;
 
    // Case 3: Old value was Even Parity,
    // new value is non Even Parity
    if (isEvenParity(oldValue)
        && !isEvenParity(new_val)) {
      diff = -1;
    }
 
    // Case 4: Old value was non Even Parity,
    // new_val is Even Parity
    if (!isEvenParity(oldValue)
        && !isEvenParity(new_val)) {
      diff = 1;
    }
 
    // Update the values of
    // nodes in segment tree
    updateValueUtil(segmentTree, 0, n - 1, i, diff, 0);
  }
 
  // Return number of Even Parity numbers
  static void queryEvenParity(int[] segmentTree, int n,
                              int queryStart,
                              int queryEnd)
  {
    int EvenParityInRange = queryEvenParityUtil(
      segmentTree, 0, n - 1, queryStart, queryEnd, 0);
 
    System.out.println(EvenParityInRange);
  }
 
  // Recursive function that constructs
  // Segment Tree for the given array
  static int constructSTUtil(int[] arr, int segmentStart,
                             int segmentEnd,
                             int[] segmentTree, int si)
  {
 
    // If there is one element in array,
    // check if it is Even Parity number
    // then store 1 in the segment tree
    // else store 0 and return
    if (segmentStart == segmentEnd) {
 
      // if arr[segmentStart] is
      // Even Parity number
      if (isEvenParity(arr[segmentStart]))
        segmentTree[si] = 1;
      else
        segmentTree[si] = 0;
 
      return segmentTree[si];
    }
 
    // If there are more than one elements,
    // then recur for left and right subtrees
    // and store the sum of the
    // two values in this node
    int mid = getMid(segmentStart, segmentEnd);
    segmentTree[si]
      = constructSTUtil(arr, segmentStart, mid,
                        segmentTree, si * 2 + 1)
      + constructSTUtil(arr, mid + 1, segmentEnd,
                        segmentTree, si * 2 + 2);
    return segmentTree[si];
  }
 
  // Function to construct a segment
  // tree from given array
  static int[] constructST(int[] arr, int n)
  {
 
    // Height of segment tree
    int x
      = (int)(Math.ceil((Math.log(n) / Math.log(2))));
 
    // Maximum size of segment tree
    int max_size = 2 * (int)Math.pow(2, x) - 1;
 
    int[] segmentTree = new int[max_size];
 
    // Fill the allocated memory st
    constructSTUtil(arr, 0, n - 1, segmentTree, 0);
 
    // Return the constructed segment tree
    return segmentTree;
  }
 
  public static void main(String[] args)
  {
    int[] arr = { 18, 15, 8, 9, 14, 5 };
    int n = arr.length;
 
    // Build segment tree from given array
    int[] segmentTree = constructST(arr, n);
 
    // Query 1: Query(start = 0, end = 4)
    int start = 0;
    int end = 4;
    queryEvenParity(segmentTree, n, start, end);
 
    // Query 2: Update(i = 3, x = 11),
    // i.e Update a[i] to x
    int i = 3;
    int x = 11;
    updateValue(arr, segmentTree, n, i, x);
 
    // Query 3: Query(start = 0, end = 4)
    start = 0;
    end = 4;
    queryEvenParity(segmentTree, n, start, end);
  }
}
 
// This code is contributed by ishankhandelwals.


Python3




# Python implementation to find
# number of Even Parity numbers
# in a subarray and performing updates
import math
# MAX
MAX = 1000
 
# Function that returns true if count
# of set bits in x is even
def isEvenParity(x):
    # parity will store the
    # count of set bits
    parity = 0
    while (x != 0):
        if (x & 1):
            parity += 1
        x = x >> 1
 
    if (parity % 2 == 0):
        return True
    else:
        return False
 
# A utility function to get
# the middle index
def getMid(s, e):
    return s + (e - s) // 2
 
# Recursive function to get the number
# of Even Parity numbers in a given range
def queryEvenParityUtil(segmentTree, segmentStart,
                        segmentEnd, queryStart,
                        queryEnd, index):
    # If segment of this node is a part
    # of given range, then return
    # the number of Even Parity numbers
    # in the segment
    if (queryStart <= segmentStart and
        queryEnd >= segmentEnd):
        return segmentTree[index]
 
    # If segment of this node
    # is outside the given range
    if (segmentEnd < queryStart or
        segmentStart > queryEnd):
        return 0
 
    # If a part of this segment
    # overlaps with the given range
    mid = getMid(segmentStart, segmentEnd)
    return queryEvenParityUtil(
               segmentTree, segmentStart, mid,
               queryStart, queryEnd, 2 * index + 1) + \
           queryEvenParityUtil(
                 segmentTree, mid + 1, segmentEnd,
                 queryStart, queryEnd, 2 * index + 2)
 
# Recursive function to update
# the nodes which have the given
# index in their range
def updateValueUtil(
        segmentTree, segmentStart,
        segmentEnd, i, diff, si):
    # Base Case:
    if (i < segmentStart or i > segmentEnd):
        return
 
    # If the input index is in range
    # of this node, then update the value
    # of the node and its children
    segmentTree[si] = segmentTree[si] + diff
    if (segmentEnd != segmentStart):
 
        mid = getMid(
            segmentStart, segmentEnd)
        updateValueUtil(
            segmentTree, segmentStart,
            mid, i, diff, 2 * si + 1)
        updateValueUtil(
            segmentTree, mid + 1, segmentEnd,
            i, diff, 2 * si + 2)
 
# Function to update a value in the
# input array and segment tree
def updateValue(arr, segmentTree,
                n, i, new_val):
    # Check for erroneous input index
    if (i < 0 or i > n - 1):
        print("Invalid Input")
        return
 
    diff = 0
    oldValue = 0
 
    oldValue = arr[i]
 
    # Update the value in array
    arr[i] = new_val
 
    # Case 1: Old and new values
    # both are Even Parity numbers
    if (isEvenParity(oldValue) and
        isEvenParity(new_val)):
        return
 
    # Case 2: Old and new values
    # both not Even Parity numbers
    if (not isEvenParity(oldValue) and
            not isEvenParity(new_val)):
        return
 
    # Case 3: Old value was Even Parity,
    # new value is non Even Parity
    if (isEvenParity(oldValue) and
            not isEvenParity(new_val)):
        diff = -1
 
    # Case 4: Old value was non Even Parity,
    # new_val is Even Parity
    if (not isEvenParity(oldValue) and
            isEvenParity(new_val)):
        diff = 1
 
    # Update the values of
    # nodes in segment tree
    updateValueUtil(segmentTree, 0,
                    n - 1, i, diff, 0)
 
# Return number of Even Parity numbers
def queryEvenParity(segmentTree,
                    n, queryStart,
                    queryEnd):
    EvenParityInRange = queryEvenParityUtil(
        segmentTree, 0, n - 1,
        queryStart, queryEnd, 0)
 
    print(EvenParityInRange)
 
# Recursive function that constructs
# Segment Tree for the given array
def constructSTUtil(arr,
                    segmentStart,
                    segmentEnd,
                    segmentTree,
                    si):
    # If there is one element in array,
    # check if it is Even Parity number
    # then store 1 in the segment tree
    # else store 0 and return
    if (segmentStart == segmentEnd):
 
        # if arr[segmentStart] is
        # Even Parity number
        if (isEvenParity(arr[segmentStart])):
            segmentTree[si] = 1
        else:
            segmentTree[si] = 0
 
        return segmentTree[si]
 
    # If there are more than one elements,
    # then recur for left and right subtrees
    # and store the sum of the
    # two values in this node
    mid = getMid(segmentStart,
                 segmentEnd)
    segmentTree[si] = constructSTUtil(
              arr, segmentStart, mid,
              segmentTree, si * 2 + 1) \
          + constructSTUtil(
                arr, mid + 1, segmentEnd,
                segmentTree, si * 2 + 2)
    return segmentTree[si]
 
 
# Function to construct a segment tree from given array
def constructST(arr, n):
    # Height of segment tree
    x = math.ceil(math.log2(n))
 
    # Maximum size of segment tree
    max_size = 2 * (2**x) - 1
 
    segmentTree = [0 for i in range(max_size)]
 
    # Fill the allocated memory st
    constructSTUtil(arr, 0, n - 1,
                    segmentTree, 0)
 
    # Return the constructed segment tree
    return segmentTree
 
# Driver Code
if __name__ == "__main__":
 
    arr = [18, 15, 8, 9, 14, 5]
    n = len(arr)
 
    # Build segment tree from given array
    segmentTree = constructST(arr, n)
 
    # Query 1: Query(start = 0, end = 4)
    start = 0
    end = 4
    queryEvenParity(segmentTree, n, start, end)
 
    # Query 2: Update(i = 3, x = 11),
    # i.e Update a[i] to x
    i = 3
    x = 11
    updateValue(arr, segmentTree, n, i, x)
 
    # Query 3: Query(start = 0, end = 4)
    start = 0
    end = 4
    queryEvenParity(
        segmentTree, n, start, end)
     
# This code is contributed by akashish__


C#




// C# implementation to find
// number of Even Parity numbers
// in a subarray and performing updates
using System;
 
class GFG{
 
public static int MAX = 1000;
 
// Function that returns true if count
// of set bits in x is even
static bool isEvenParity(int x)
{
     
    // parity will store the
    // count of set bits
    int parity = 0;
     
    while (x != 0)
    {
        if ((x & 1) != 0)
            parity++;
             
        x = x >> 1;
    }
 
    if (parity % 2 == 0)
        return true;
    else
        return false;
}
 
// A utility function to get
// the middle index
static int getMid(int s, int e)
{
    return s + (e - s) / 2;
}
 
// Recursive function to get the number
// of Even Parity numbers in a given range
static int queryEvenParityUtil(int[] segmentTree,
                               int segmentStart,
                               int segmentEnd,
                               int queryStart,
                               int queryEnd, int index)
{
     
    // If segment of this node is a part
    // of given range, then return
    // the number of Even Parity numbers
    // in the segment
    if (queryStart <= segmentStart &&
        queryEnd >= segmentEnd)
        return segmentTree[index];
 
    // If segment of this node
    // is outside the given range
    if (segmentEnd < queryStart ||
        segmentStart > queryEnd)
        return 0;
 
    // If a part of this segment
    // overlaps with the given range
    int mid = getMid(segmentStart, segmentEnd);
    return queryEvenParityUtil(segmentTree, segmentStart,
                               mid, queryStart, queryEnd,
                               2 * index + 1) +
           queryEvenParityUtil(segmentTree, mid + 1,
                               segmentEnd, queryStart,
                               queryEnd, 2 * index + 2);
}
 
// Recursive function to update
// the nodes which have the given
// index in their range
static void updateValueUtil(int[] segmentTree,
                            int segmentStart,
                            int segmentEnd, int i,
                            int diff, int si)
{
     
    // Base Case:
    if (i < segmentStart || i > segmentEnd)
        return;
 
    // If the input index is in range
    // of this node, then update the value
    // of the node and its children
    segmentTree[si] = segmentTree[si] + diff;
     
    if (segmentEnd != segmentStart)
    {
        int mid = getMid(segmentStart, segmentEnd);
        updateValueUtil(segmentTree, segmentStart, mid,
                        i, diff, 2 * si + 1);
        updateValueUtil(segmentTree, mid + 1,
                        segmentEnd, i, diff,
                        2 * si + 2);
    }
}
 
// Function to update a value in the
// input array and segment tree
static void updateValue(int[] arr, int[] segmentTree,
                        int n, int i, int new_val)
{
     
    // Check for erroneous input index
    if (i < 0 || i > n - 1)
    {
        Console.WriteLine("Invalid Input");
        return;
    }
 
    int diff = 0, oldValue = 0;
 
    oldValue = arr[i];
 
    // Update the value in array
    arr[i] = new_val;
 
    // Case 1: Old and new values
    // both are Even Parity numbers
    if (isEvenParity(oldValue) &&
        isEvenParity(new_val))
        return;
 
    // Case 2: Old and new values
    // both not Even Parity numbers
    if (!isEvenParity(oldValue) &&
        !isEvenParity(new_val))
        return;
 
    // Case 3: Old value was Even Parity,
    // new value is non Even Parity
    if (isEvenParity(oldValue) &&
       !isEvenParity(new_val))
    {
        diff = -1;
    }
 
    // Case 4: Old value was non Even Parity,
    // new_val is Even Parity
    if (!isEvenParity(oldValue) &&
        !isEvenParity(new_val))
    {
        diff = 1;
    }
 
    // Update the values of
    // nodes in segment tree
    updateValueUtil(segmentTree, 0, n - 1, i, diff, 0);
}
 
// Return number of Even Parity numbers
static void queryEvenParity(int[] segmentTree, int n,
                            int queryStart,
                            int queryEnd)
{
    int EvenParityInRange = queryEvenParityUtil(
        segmentTree, 0, n - 1, queryStart, queryEnd, 0);
 
    Console.WriteLine(EvenParityInRange);
}
 
// Recursive function that constructs
// Segment Tree for the given array
static int constructSTUtil(int[] arr, int segmentStart,
                           int segmentEnd,
                           int[] segmentTree, int si)
{
     
    // If there is one element in array,
    // check if it is Even Parity number
    // then store 1 in the segment tree
    // else store 0 and return
    if (segmentStart == segmentEnd)
    {
         
        // if arr[segmentStart] is
        // Even Parity number
        if (isEvenParity(arr[segmentStart]))
            segmentTree[si] = 1;
        else
            segmentTree[si] = 0;
 
        return segmentTree[si];
    }
 
    // If there are more than one elements,
    // then recur for left and right subtrees
    // and store the sum of the
    // two values in this node
    int mid = getMid(segmentStart, segmentEnd);
    segmentTree[si] = constructSTUtil(arr, segmentStart, mid,
                                      segmentTree, si * 2 + 1) +
                      constructSTUtil(arr, mid + 1, segmentEnd,
                                      segmentTree, si * 2 + 2);
    return segmentTree[si];
}
 
// Function to construct a segment
// tree from given array
static int[] constructST(int[] arr, int n)
{
     
    // Height of segment tree
    int x = (int)(Math.Ceiling(Math.Log(n, 2)));
 
    // Maximum size of segment tree
    int max_size = 2 * (int)Math.Pow(2, x) - 1;
 
    int[] segmentTree = new int[max_size];
 
    // Fill the allocated memory st
    constructSTUtil(arr, 0, n - 1, segmentTree, 0);
 
    // Return the constructed segment tree
    return segmentTree;
}
 
// Driver Code
public static void Main()
{
    int[] arr = { 18, 15, 8, 9, 14, 5 };
    int n = arr.Length;
 
    // Build segment tree from given array
    int[] segmentTree = constructST(arr, n);
 
    // Query 1: Query(start = 0, end = 4)
    int start = 0;
    int end = 4;
    queryEvenParity(segmentTree, n, start, end);
 
    // Query 2: Update(i = 3, x = 11),
    // i.e Update a[i] to x
    int i = 3;
    int x = 11;
    updateValue(arr, segmentTree, n, i, x);
 
    // Query 3: Query(start = 0, end = 4)
    start = 0;
    end = 4;
    queryEvenParity(segmentTree, n, start, end);
}
}
 
// This code is contributed by ukasp


Javascript




// JavaScript implementation to find
// number of Even Parity numbers
// in a subarray and performing updates
 
const MAX = 1000;
 
// Function that returns true if count
// of set bits in x is even
function isEvenParity(x) {
    // parity will store the count of set bits
    let parity = 0;
    while (x != 0) {
    if (x & 1) {
    parity++;
    }
    x = x >> 1;
    }
 
 
 
    if (parity % 2 == 0) {
        return true;
    } else {
        return false;
    }
 
}
 
// A utility function to get
// the middle index
function getMid(s, e) {
    return s + Math.floor((e - s) / 2);
}
 
// Recursive function to get the number
// of Even Parity numbers in a given range
function queryEvenParityUtil(segmentTree, segmentStart,segmentEnd, queryStart,queryEnd, index)
{
    // If segment of this node is a part
    // of given range, then return
    // the number of Even Parity numbers
    // in the segment
    if (queryStart <= segmentStart && queryEnd >= segmentEnd)
        return segmentTree[index];
     // If segment of this node
    // is outside the given range
    if (segmentEnd < queryStart || segmentStart > queryEnd)
        return 0;
      // If a part of this segment
      // overlaps with the given range
    let mid = getMid(segmentStart, segmentEnd);
    return queryEvenParityUtil(segmentTree, segmentStart, mid,queryStart, queryEnd, 2 * index + 1)
    + queryEvenParityUtil(segmentTree, mid + 1, segmentEnd,queryStart, queryEnd, 2 * index + 2);
 
}
 
// Recursive function to update
// the nodes which have the given
// index in their range
function updateValueUtil(
segmentTree, segmentStart,
segmentEnd, i, diff, si)
{
// Base Case:
if (i < segmentStart || i > segmentEnd)
return;
 
 
 
// If the input index is in range
// of this node, then update the value
// of the node and its children
segmentTree[si] = segmentTree[si] + diff;
if (segmentEnd != segmentStart) {
    let mid = getMid(segmentStart, segmentEnd);
    updateValueUtil(
        segmentTree, segmentStart,
        mid, i, diff, 2 * si + 1);
    updateValueUtil(
        segmentTree, mid + 1, segmentEnd,
        i, diff, 2 * si + 2);
}
 
}
 
// Function to update a value in the
// input array and segment tree
function updateValue(arr, segmentTree,n, i, new_val)
{
// Check for erroneous input index
if (i < 0 || i > n - 1) {
console.log("Invalid Input");
return;
}
 
 
let diff, oldValue;
 
oldValue = arr[i];
 
// Update the value in array
arr[i] = new_val;
 
// Case 1: Old and new values
// both are Even Parity numbers
if (isEvenParity(oldValue)
    && isEvenParity(new_val))
    return;
 
// Case 2: Old and new values
// both not even parity numbers
if(!isEvenParity(oldValue) && !isEvenParity(new_val))
    return;
// Case 3: Old value was Even Parity,
    // new value is non Even Parity
    if (isEvenParity(oldValue)
        && !isEvenParity(new_val)) {
        diff = -1;
    }
 
    // Case 4: Old value was non Even Parity,
    // new_val is Even Parity
    if (!isEvenParity(oldValue)
        && !isEvenParity(new_val)) {
        diff = 1;
    }
    updateValueUtil(segmentTree,0,n-1,i,diff,0);
     
}
function queryEvenParity(segmentTree, n, queryStart, queryEnd) {
  const evenParityInRange = queryEvenParityUtil(segmentTree, 0, n - 1, queryStart, queryEnd, 0);
  console.log(evenParityInRange);
}
 
// Recursive function that constructs Segment Tree for the given array
function constructSTUtil(arr, segmentStart, segmentEnd, segmentTree, si) {
    // If there is one element in array, check if it is Even Parity number
    // then store 1 in the segment tree else store 0 and return
    if (segmentStart === segmentEnd) {
    // if arr[segmentStart] is Even Parity number
    if (isEvenParity(arr[segmentStart])) {
    segmentTree[si] = 1;
    } else {
    segmentTree[si] = 0;
    }
    return segmentTree[si];
    }
    // If there are more than one elements,
    // then recur for left and right subtrees and store the sum of the two values in this node
    const mid = getMid(segmentStart, segmentEnd);
    segmentTree[si] = constructSTUtil(arr, segmentStart, mid, segmentTree, si * 2 + 1)
    + constructSTUtil(arr, mid + 1, segmentEnd, segmentTree, si * 2 + 2);
    return segmentTree[si];
}
 
// Function to construct a segment tree from given array
function constructST(arr, n) {
    // Height of segment tree
    const x = Math.ceil(Math.log2(n));
 
    // Maximum size of segment tree
    const max_size = 2 * Math.pow(2, x) - 1;
 
    const segmentTree = new Array(max_size).fill(0);
 
    // Fill the allocated memory
    constructSTUtil(arr, 0, n - 1, segmentTree, 0);
 
    // Return the constructed segment tree
    return segmentTree;
}
 
// Driver Code
function main() {
      const arr = [18, 15, 8, 9, 14, 5];
      const n = arr.length;
 
      // Build segment tree from given array
      const segmentTree = constructST(arr, n);
 
      // Query 1: Query(start = 0, end = 4)
      const start = 0;
      const end = 4;
      queryEvenParity(segmentTree, n, start, end);
 
      // Query 2: Update(i = 3, x = 11), i.e Update a[i] to x
      const i = 3;
      const x = 11;
      updateValue(arr, segmentTree, n, i, x);
 
      // Query 3: Query(start = 0, end = 4)
      queryEvenParity(segmentTree, n, start, end);
}
 
main(); // calling the driver code function. Note: updateValue function is not included in this code snippet. It needs to be defined to run the code properly.


Output: 

3
2

 

Time Complexity: O(n*log n),  where n is the number of elements in the input array.
Space Complexity: O(n),  where n is the number of elements in the input array.



Last Updated : 17 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads