Count number of smallest elements in given range

Given an array of N numbers and Q queries, each query consists of L and R. We need to write a program that prints the number of occurrence of the smallest element in the range L-R.

Examples:

Input: a[] = {1, 1, 2, 4, 3, 3}
        Q = 2 
        L = 1 R = 4 
        L = 3 R = 6
Output: 2 
        1 
Explanation: The smallest element in range 1-4 
is 1 which occurs 2 times. The smallest element
in the range 3-6 is 2 which occurs once.  

Input : a[] = {1, 2, 3, 3, 1}
        Q = 2 
        L = 1 R = 5 
        L = 3 R = 4
Output : 2
         2

A normal approach will be to iterate from L-R and find out the smallest element in the range. Iterate again in the range L-R and count the number of times the smallest element occurs in the range L-R. In the worst case, the complexity will be O(N) if L=1 and R=N.



An efficient approach will be to use Segment Trees to solve the above problem. At each node of the segment tree, smallest element and count of smallest element is stored. At leaf nodes, the array element is stored in the minimum and count stores 1. For all other nodes except the leaf nodes, we merge the right and left nodes following the given conditions:

1. min(left_subtree) < min(right_subtree):
node.min=min(left_subtree), node.count = left_subtree.count
2. min(left_subtree) > min(right_subtree):
node.min=min(right_subtree), node.count=right_subtree.count
3. min(left_subtree) = min(right_subtree):
node.min=min(left_subtree) or min(right_subtree), node.count=left_subtree.count + right_subtree.count

Given below is the implementation of the above approach:

filter_none

edit
close

play_arrow

link
brightness_4
code

// CPP program to Count number of occurrence of
// smallest element in range L-R
#include <bits/stdc++.h>
using namespace std;
  
#define N 100005
  
// predefines the tree with nodes
// storing min and count
struct node {
    int min;
    int cnt;
} tree[5 * N];
  
// function to construct the tree
void buildtree(int low, int high, int pos, int a[])
{
    // base condition
    if (low == high) {
  
        // leaf node has a single element
        tree[pos].min = a[low];
        tree[pos].cnt = 1;
        return;
    }
  
    int mid = (low + high) >> 1;
    // left-subtree
    buildtree(low, mid, 2 * pos + 1, a);
  
    // right-subtree
    buildtree(mid + 1, high, 2 * pos + 2, a);
  
    // left subtree has the minimum element
    if (tree[2 * pos + 1].min < tree[2 * pos + 2].min) {
        tree[pos].min = tree[2 * pos + 1].min;
        tree[pos].cnt = tree[2 * pos + 1].cnt;
    }
  
    // right subtree has the minimum element
    else if (tree[2 * pos + 1].min > tree[2 * pos + 2].min) {
        tree[pos].min = tree[2 * pos + 2].min;
        tree[pos].cnt = tree[2 * pos + 2].cnt;
    }
  
    // both subtree has the same minimum element
    else {
        tree[pos].min = tree[2 * pos + 1].min;
        tree[pos].cnt = tree[2 * pos + 1].cnt + tree[2 * pos + 2].cnt;
    }
}
  
// function that answers every query
node query(int s, int e, int low, int high, int pos)
{
    node dummy;
    // out of range
    if (e < low or s > high) {
        dummy.min = dummy.cnt = INT_MAX;
        return dummy;
    }
  
    // in range
    if (s >= low and e <= high) {
        return tree[pos];
    }
  
    int mid = (s + e) >> 1;
  
    // left-subtree
    node ans1 = query(s, mid, low, high, 2 * pos + 1);
  
    // right-subtree
    node ans2 = query(mid + 1, e, low, high, 2 * pos + 2);
  
    node ans;
    ans.min = min(ans1.min, ans2.min);
  
    // add count when min is same of both subtree
    if (ans1.min == ans2.min)
        ans.cnt = ans2.cnt + ans1.cnt;
  
    // store the minimal's count
    else if (ans1.min < ans2.min)
        ans.cnt = ans1.cnt;
  
    else
        ans.cnt = ans2.cnt;
  
    return ans;
}
  
// function to answer query in range l-r
int answerQuery(int a[], int n, int l, int r)
{
    // calls the function which returns a node
    // this function returns the count which
    // will be the answer
    return query(0, n - 1, l - 1, r - 1, 0).cnt;
}
  
// Driver Code
int main()
{
    int a[] = { 1, 1, 2, 4, 3, 3 };
  
    int n = sizeof(a) / sizeof(a[0]);
    buildtree(0, n - 1, 0, a);
    int l = 1, r = 4;
  
    // answers 1-st query
    cout << answerQuery(a, n, l, r) << endl;
  
    l = 2, r = 6;
    // answers 2nd query
    cout << answerQuery(a, n, l, r) << endl;
    return 0;
}

chevron_right


Output:

2
1

Time Complexity: O(n) for the construction of tree. O(log n) for every query.



My Personal Notes arrow_drop_up

Striver(underscore)79 at Codechef and codeforces D

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.