Open In App

Queries for count of array elements with values in given range with updates

Given an array arr[] of size N and a matrix Q consisting of queries of the following two types: 

Examples: 



Input: arr[] = {1, 2, 2, 3, 4, 4, 5, 6}, Q = {{1, {3, 5}}, {1, {2, 4}}, {1, {1, 2}}, {2, {1, 7}}, {1, {1, 2}}} 
Output: 4 5 3 2 
Explanation: 
Array elements from the range [3, 5] are {3, 4, 4, 5} 
Array elements from the range [2, 4] are {2, 2, 3, 4, 4} 
Array elements from the range [1, 2] are {1, 2, 2} 
Replacing arr[1] by 7 modifies the array to {1, 7, 2, 3, 4, 4, 5, 6} 
Elements that lie in range [1, 2] are {1, 2}

Input: arr = {5, 5, 1, 3, 4, 4, 2, 3}, Q = {{1, {3, 6}}, {1, {2, 4}}, {1, {10, 20}}} 
Output: 6 5 0 
Explanation: 
Array elements from the range [3, 6] are {3, 3, 4, 4, 5, 5} 
Array elements from the range [2, 4] are {2, 3, 3, 4, 4} 
No element from the range [10, 20] exists in the array. 



Naive Approach: 
The simplest approach to solve this problem is as follows: 

Below is the implementation of the above approach:




// C++ code for queries for number
// of elements that lie in range
// [l, r] (with updates)
#include <bits/stdc++.h>
using namespace std;
 
// Function to set arr[index] = x
void setElement(int* arr, int n,
                int index, int x)
{
    arr[index] = x;
}
 
// Function to get count of elements
// that lie in range [l, r]
int getCount(int* arr, int n,
            int l, int r)
{
    int count = 0;
 
    // Traverse array
    for (int i = 0; i < n; i++) {
 
        // If element lies in the
        // range [L, R]
        if (arr[i] >= l
            && arr[i] <= r) {
 
            // Increase count
            count++;
        }
    }
    return count;
}
 
// Function to solve each query
void SolveQuery(int arr[], int n,
                vector<pair<int,
                            pair<int, int> > >
                    Q)
{
    int x;
 
    for (int i = 0; i < Q.size(); i++) {
        if (Q[i].first == 1) {
            x = getCount(arr, n,
                        Q[i].second.first,
                        Q[i].second.second);
 
            cout << x << " ";
        }
        else {
            setElement(arr, n,
                    Q[i].second.first,
                    Q[i].second.second);
        }
    }
}
 
// Driver Code
int main()
{
    int arr[] = { 1, 2, 2, 3, 4, 4, 5, 6 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    vector<pair<int, pair<int, int> > > Q
        = { { 1, { 3, 5 } },
            { 1, { 2, 4 } },
            { 1, { 1, 2 } },
            { 2, { 1, 7 } },
            { 1, { 1, 2 } } };
    SolveQuery(arr, n, Q);
 
    return 0;
}




// Java code for queries for number
// of elements that lie in range
// [l, r] (with updates)
import java.util.*;
import java.lang.*;
 
class GFG{
     
// Function to set arr[index] = x
static void setElement(int[] arr, int n,
                       int index, int x)
{
    arr[index] = x;
}
 
// Function to get count of elements
// that lie in range [l, r]
static int getCount(int[] arr, int n,
                    int l, int r)
{
    int count = 0;
     
    // Traverse array
    for(int i = 0; i < n; i++)
    {
         
        // If element lies in the
        // range [L, R]
        if (arr[i] >= l && arr[i] <= r)
        {
            // Increase count
            count++;
        }
    }
    return count;
}
 
// Function to solve each query
static void SolveQuery(int arr[], int n,
                       ArrayList<List<Integer>> Q)
{
    int x;
  
    for(int i = 0; i < Q.size(); i++)
    {
        if (Q.get(i).get(0) == 1)
        {
            x = getCount(arr, n,
                         Q.get(i).get(1),
                         Q.get(i).get(2));
  
            System.out.print(x + " ");
        }
        else
        {
            setElement(arr, n,
                       Q.get(i).get(1),
                       Q.get(i).get(2));
        }
    }
}
  
// Driver code
public static void main (String[] args)
{
    int arr[] = { 1, 2, 2, 3, 4, 4, 5, 6 };
    int n = arr.length;
     
    ArrayList<List<Integer>> Q = new ArrayList<>();
    Q.add(Arrays.asList(1, 3, 5));
    Q.add(Arrays.asList(1, 2, 4)); 
    Q.add(Arrays.asList(1, 1, 2));
    Q.add(Arrays.asList(2, 1, 7));
    Q.add(Arrays.asList(1, 1, 2));
     
    SolveQuery(arr, n, Q);
}
}
 
// This code is contributed by offbeat




# Python3 code for queries for number
# of elements that lie in range
# [l, r] (with updates)
from typing import Generic, List, TypeVar
 
T = TypeVar('T')
V = TypeVar('V')
 
class Pair(Generic[V, T]):
     
    def __init__(self, first: V, second: T) -> None:
         
        self.first = first
        self.second = second
 
# Function to set arr[index] = x
def setElement(arr: List[int], n: int,
                   index: int, x: int) -> None:
                        
    arr[index] = x
 
# Function to get count of elements
# that lie in range [l, r]
def getCount(arr: List[int], n: int,
                     l: int, r: int) -> int:
 
    count = 0
 
    # Traverse array
    for i in range(n):
 
        # If element lies in the
        # range [L, R]
        if (arr[i] >= l and arr[i] <= r):
 
            # Increase count
            count += 1
 
    return count
 
# Function to solve each query
def SolveQuery(arr: List[int], n: int,
            Q: List[Pair[int, Pair[int, int]]]):
 
    x = 0
 
    for i in range(len(Q)):
        if (Q[i].first == 1):
            x = getCount(arr, n, Q[i].second.first,
                                 Q[i].second.second)
            print(x, end = " ")
        else:
            setElement(arr, n, Q[i].second.first,
                               Q[i].second.second)
 
# Driver Code
if __name__ == "__main__":
 
    arr = [ 1, 2, 2, 3, 4, 4, 5, 6 ]
    n = len(arr)
 
    Q = [ Pair(1, Pair(3, 5)),
          Pair(1, Pair(2, 4)),
          Pair(1, Pair(1, 2)),
          Pair(2, Pair(1, 7)),
          Pair(1, Pair(1, 2)) ]
           
    SolveQuery(arr, n, Q)
 
# This code is contributed by sanjeev2552




// C# code for queries for number
// of elements that lie in range
// [l, r] (with updates)
using System;
using System.Collections.Generic;
 
class GFG{
 
// Function to set arr[index] = x
static void setElement(int[] arr, int n,
                       int index, int x)
{
    arr[index] = x;
}
 
// Function to get count of elements
// that lie in range [l, r]
static int getCount(int[] arr, int n,
                    int l, int r)
{
    int count = 0;
     
    // Traverse array
    for(int i = 0; i < n; i++)
    {
         
        // If element lies in the
        // range [L, R]
        if (arr[i] >= l && arr[i] <= r)
         
            // Increase count
            count += 1;
    }
    return count;
}
 
// Function to solve each query
static void SolveQuery(int[] arr, int n,
             List<List<int>> Q)
{
    int x;
 
    for(int i = 0; i < Q.Count; i++)
    {
        if (Q[i][0] == 1)
        {
            x = getCount(arr, n,
                         Q[i][1],
                         Q[i][2]);
 
            Console.Write(x + " ");
        }
        else
        {
            setElement(arr, n,
                       Q[i][1],
                       Q[i][2]);
        }
    }
}
 
// Driver code
public static void Main(string[] args)
{
    int[] arr = { 1, 2, 2, 3, 4, 4, 5, 6 };
    int n = arr.Length;
 
    List<List<int>> myList = new List<List<int>>();
    myList.Add(new List<int>{ 1, 3, 5 });
    myList.Add(new List<int>{ 1, 2, 4 });
    myList.Add(new List<int>{ 1, 1, 2 });
    myList.Add(new List<int>{ 2, 1, 7 });
    myList.Add(new List<int>{ 1, 1, 2 });
 
    SolveQuery(arr, n, myList);
}
}
 
// This code is contributed by grand_master




<script>
// Javascript code for queries for number
// of elements that lie in range
// [l, r] (with updates)
 
// Function to set arr[index] = x
function setElement(arr, n, index, x)
{
    arr[index] = x;
}
 
// Function to get count of elements
// that lie in range [l, r]
function getCount(arr, n, l, r)
{
    let count = 0;
 
    // Traverse array
    for (let i = 0; i < n; i++) {
 
        // If element lies in the
        // range [L, R]
        if (arr[i] >= l
            && arr[i] <= r) {
 
            // Increase count
            count++;
        }
    }
    return count;
}
 
// Function to solve each query
function SolveQuery(arr, n, Q) {
    let x;
 
    for (let i = 0; i < Q.length; i++) {
        if (Q[i][0] == 1) {
            x = getCount(arr, n,
                Q[i][1][0],
                Q[i][1][1]);
 
            document.write(x + " ");
        }
        else {
            setElement(arr, n,
                Q[i][1][0],
                Q[i][1][1]);
        }
    }
}
 
// Driver Code
let arr = [ 1, 2, 2, 3, 4, 4, 5, 6 ];
let n = arr.length;
 
let Q
    = [[1, [3, 5]],
    [1, [2, 4]],
    [1, [1, 2]],
    [2, [1, 7]],
    [1, [1, 2]]];
SolveQuery(arr, n, Q);
 
// This code is contributed by _saurabh_jaiswal.
</script>

Output: 
4 5 3 2

 

Time Complexity: O(Q * N) 
Auxiliary Space: O(1)

Efficient Approach: 
The above approach can be optimized using Fenwick Tree. Follow the steps below to solve the problem: 

getSum(R) – getSum(L – 1)

Below is the implementation of the above approach:




// C++ code for queries for number
// of elements that lie in range
// [l, r] (with updates)
#include <bits/stdc++.h>
using namespace std;
 
class FenwickTree {
public:
    int* BIT;
    int N;
 
    FenwickTree(int N)
    {
        this->N = N;
        BIT = new int[N];
        for (int i = 0; i < N; i++) {
            BIT[i] = 0;
        }
    }
 
    // Traverse all ancestors and
    // increase frequency of index
    void update(int index, int increment)
    {
        while (index < N) {
 
            // Increase count of the current
            // node of BIT Tree
            BIT[index] += increment;
 
            // Update index to that of parent
            // in update View
            index += (index & -index);
        }
    }
    // Function to return the
    // sum of arr[0..index]
    int getSum(int index)
    {
        int sum = 0;
 
        // Traverse ancestors of
        // BITree[index]
        while (index > 0) {
 
            // Add current element of
            // BITree to sum
            sum += BIT[index];
 
            // Move index to parent node in
            // getSum View
            index -= (index & -index);
        }
        return sum;
    }
};
 
// Function to set arr[index] = x
void setElement(int* arr, int n,
                int index, int x,
                FenwickTree* fenTree)
{
    int removedElement = arr[index];
    fenTree->update(removedElement, -1);
    arr[index] = x;
    fenTree->update(x, 1);
}
 
// Function to get count of
// elements that lie in
// range [l, r]
int getCount(int* arr, int n,
            int l, int r,
            FenwickTree* fenTree)
{
    int count = fenTree->getSum(r)
                - fenTree->getSum(l - 1);
    return count;
}
 
// Function to solve each query
void SolveQuery(int arr[], int n,
                vector<pair<int,
                            pair<int, int> > >
                    Q)
{
    int N = 100001;
 
    FenwickTree* fenTree = new FenwickTree(N);
 
    for (int i = 0; i < n; i++) {
        fenTree->update(arr[i], 1);
    }
 
    int x;
 
    for (int i = 0; i < Q.size(); i++) {
        if (Q[i].first == 1) {
            x = getCount(arr, n,
                        Q[i].second.first,
                        Q[i].second.second,
                        fenTree);
 
            cout << x << " ";
        }
        else {
            setElement(arr, n,
                    Q[i].second.first,
                    Q[i].second.second,
                    fenTree);
        }
    }
}
 
// Driver Code
int main()
{
    int arr[] = { 1, 2, 2, 3,
                4, 4, 5, 6 };
 
    int n = sizeof(arr) / sizeof(arr[0]);
    vector<pair<int, pair<int, int> > > Q
        = { { 1, { 3, 5 } },
            { 1, { 2, 4 } },
            { 1, { 1, 2 } },
            { 2, { 1, 7 } },
            { 1, { 1, 2 } } };
 
    SolveQuery(arr, n, Q);
 
    return 0;
}
 
//code contributed by dhanshriborse




// Java code for queries for number
// of elements that lie in range
// [l, r] (with updates)
 
import java.util.*;
 
class FenwickTree {
    int N;
    int[] BIT;
    public FenwickTree(int N)
    {
        this.N = N;
        BIT = new int[N];
    }
 
    public void update(int index, int increment)
    {
        while (index < N) {
            BIT[index] += increment;
            index += index & -index;
        }
    }
 
    public int getSum(int index)
    {
        int sum = 0;
        while (index > 0) {
            sum += BIT[index];
            index -= index & -index;
        }
        return sum;
    }
}
 
public class Main {
    // Function to return the sum of arr[0..index]
    public static void setElement(int[] arr, int n,
                                  int index, int x,
                                  FenwickTree fenTree)
    {
        int removedElement = arr[index];
        fenTree.update(removedElement, -1);
        arr[index] = x;
        fenTree.update(x, 1);
    }
    // Function to get count of elements that lie in range
    // [l, r]
    public static int getCount(int[] arr, int n, int l,
                               int r, FenwickTree fenTree)
    {
        int count
            = fenTree.getSum(r) - fenTree.getSum(l - 1);
        return count;
    }
 
    // Function to solve each query
    public static void SolveQuery(int[] arr, int n,
                                  ArrayList<int[]> Q)
    {
        int N = 100001;
        FenwickTree fenTree = new FenwickTree(N);
        for (int i = 0; i < n; i++) {
            fenTree.update(arr[i], 1);
        }
 
        for (int i = 0; i < Q.size(); i++) {
            if (Q.get(i)[0] == 1) {
                int x = getCount(arr, n, Q.get(i)[1],
                                 Q.get(i)[2], fenTree);
                System.out.print(x + " ");
            }
            else {
                setElement(arr, n, Q.get(i)[1], Q.get(i)[2],
                           fenTree);
            }
        }
    }
 
    public static void main(String[] args)
    {
        int[] arr = { 1, 2, 2, 3, 4, 4, 5, 6 };
        int n = arr.length;
        ArrayList<int[]> Q = new ArrayList<>();
        Q.add(new int[] { 1, 3, 5 });
        Q.add(new int[] { 1, 2, 4 });
        Q.add(new int[] { 1, 1, 2 });
        Q.add(new int[] { 2, 1, 7 });
        Q.add(new int[] { 1, 1, 2 });
 
        SolveQuery(arr, n, Q);
    }
}
 
// Contributed by adityasharmadev01




# Python code for queries for number
# of elements that lie in range
# [l, r] (with updates)
import bisect
class FenwickTree:
    def __init__(self, N):
        self.N = N
        self.BIT = [0]*N
 
    def update(self, index, increment):
        while index < self.N:
            self.BIT[index] += increment
            index += index & -index
             
             
#Traverse all ancestors and
#increase frequency of index
 
    def getSum(self, index):
        sum = 0
        while index > 0:
         #Increase count of the current
         #node of BIT Tree
           
            sum += self.BIT[index]
 # Update index to that of parent
 #in update View
            index -= index & -index
        return sum
 
# Function to return the
#sum of arr[0..index]
def setElement(arr, n, index, x, fenTree):
    removedElement = arr[index]
    fenTree.update(removedElement, -1)
    arr[index] = x
    fenTree.update(x, 1)
 
#Function to get count of
#elements that lie in
#range [l, r]
def getCount(arr, n, l, r, fenTree):
    count = fenTree.getSum(r) - fenTree.getSum(l - 1)
    return count
#Function to solve each query
def SolveQuery(arr, n, Q):
    N = 100001
    fenTree = FenwickTree(N)
    for i in range(n):
        fenTree.update(arr[i], 1)
 
    for i in range(len(Q)):
        if Q[i][0] == 1:
            x = getCount(arr, n, Q[i][1][0], Q[i][1][1], fenTree)
            print(x, end=" ")
        else:
            setElement(arr, n, Q[i][1][0], Q[i][1][1], fenTree)
 
arr = [1, 2, 2, 3, 4, 4, 5, 6]
n = len(arr)
Q = [
    (1, (3, 5)),
    (1, (2, 4)),
    (1, (1, 2)),
    (2, (1, 7)),
    (1, (1, 2))
]
 
SolveQuery(arr, n, Q)
 
#COde contributed by dhanshriborse




// C# code for queries for number
// of elements that lie in range
// [l, r] (with updates)
 
using System;
using System.Collections.Generic;
 
// FenwickTree class definition
public class FenwickTree
{
    int N;
    int[] BIT;
     
    // Constructor
    public FenwickTree(int N)
    {
        this.N = N;
        BIT = new int[N];
    }
     
    // Update method
    public void update(int index, int increment)
    {
        while (index < N)
        {
            BIT[index] += increment;
            index += index & -index;
        }
    }
     
    // Method to get the sum of the tree
    // in O(logn) time
    public int getSum(int index)
    {
        int sum = 0;
        while (index > 0)
        {
            sum += BIT[index];
            index -= index & -index;
        }
        return sum;
    }
}
 
class GFG
{
    // Function to return the sum of arr[0..index]
    public static void setElement(int[] arr, int n,
                                  int index, int x,
                                  FenwickTree fenTree)
    {
        int removedElement = arr[index];
        fenTree.update(removedElement, -1);
        arr[index] = x;
        fenTree.update(x, 1);
    }
    // Function to get count of elements that lie in range
    // [l, r]
    public static int getCount(int[] arr, int n, int l,
                               int r, FenwickTree fenTree)
    {
        int count
            = fenTree.getSum(r) - fenTree.getSum(l - 1);
        return count;
    }
 
    // Function to solve each query
    public static void SolveQuery(int[] arr, int n,
                                  List<int[]> Q)
    {
        int N = 100001;
        FenwickTree fenTree = new FenwickTree(N);
        for (int i = 0; i < n; i++)
        {
            fenTree.update(arr[i], 1);
        }
 
        for (int i = 0; i < Q.Count; i++)
        {
            if (Q[i][0] == 1)
            {
                int x = getCount(arr, n, Q[i][1],
                                 Q[i][2], fenTree);
                Console.Write(x + " ");
            }
            else
            {
                setElement(arr, n, Q[i][1], Q[i][2],
                           fenTree);
            }
        }
    }
     
    // Driver code
    public static void Main(string[] args)
    {
        int[] arr = { 1, 2, 2, 3, 4, 4, 5, 6 };
        int n = arr.Length;
        List<int[]> Q = new List<int[] >();
        Q.Add(new int[] { 1, 3, 5 });
        Q.Add(new int[] { 1, 2, 4 });
        Q.Add(new int[] { 1, 1, 2 });
        Q.Add(new int[] { 2, 1, 7 });
        Q.Add(new int[] { 1, 1, 2 });
         
        // Function call
        SolveQuery(arr, n, Q);
    }
}




// Define the FenwickTree class
class FenwickTree {
  constructor(N) {
    this.N = N;
    this.BIT = new Array(N).fill(0);
  }
 
  // Update the value of the given index with the given increment
  update(index, increment) {
    while (index < this.N) {
      this.BIT[index] += increment;
      // Update the index to its parent node in the BIT tree
      index += index & -index;
    }
  }
 
  // Get the sum of values up to the given index
  getSum(index) {
    let sum = 0;
    while (index > 0) {
      // Increase the count of the current node of the BIT tree
      sum += this.BIT[index];
      // Update the index to its parent node in the update view
      index -= index & -index;
    }
    return sum;
  }
}
 
// Set the value of the element at the given index
// to the given value, and update the Fenwick tree accordingly
function setElement(arr, n, index, x, fenTree) {
  let removedElement = arr[index];
  fenTree.update(removedElement, -1);
  arr[index] = x;
  fenTree.update(x, 1);
}
 
// Get the count of elements in the given array
// that lie in the range [l, r] using the Fenwick tree
function getCount(arr, n, l, r, fenTree) {
  let count = fenTree.getSum(r) - fenTree.getSum(l - 1);
  return count;
}
 
// Solve each query in the given array of queries
function SolveQuery(arr, n, Q) {
  let N = 100001;
  let fenTree = new FenwickTree(N);
  // Initialize the Fenwick tree with the values in the array
  for (let i = 0; i < n; i++) {
    fenTree.update(arr[i], 1);
  }
 
  // Process each query in the array
  for (let i = 0; i < Q.length; i++) {
    if (Q[i][0] == 1) {
     
      // If the query is of type 1, get the count of elements in the range [l, r]
      let x = getCount(arr, n, Q[i][1][0], Q[i][1][1], fenTree);
       
      // Print the count to the console
      process.stdout.write(x + " ");
    } else {
     
      // If the query is of type 2, update the value of an element in the array
      setElement(arr, n, Q[i][1][0], Q[i][1][1], fenTree);
    }
  }
}
 
// Define the input array and the array of queries
let arr = [1, 2, 2, 3, 4, 4, 5, 6];
let n = arr.length;
let Q = [
  [1, [3, 5]],
  [1, [2, 4]],
  [1, [1, 2]],
  [2, [1, 7]],
  [1, [1, 2]],
];
 
// Call the SolveQuery function with
// the input array and the array of queries
SolveQuery(arr, n, Q);

Output: 
4 5 3 2

 

Time Complexity: O(n*log(N) + Q*log(N)) 
Auxiliary Space: O(maxm), where maxm is the maximum element present in the array.
 


Article Tags :