Open In App

Count number of smallest elements in given range

Last Updated : 28 Apr, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

You are given an array arr[] of size n consisting of integers. Additionally, you are given q queries. Each query is represented by a pair [l, r], where 0 ≤ l ≤ r < n.
For each query, determine the number of times the smallest element appears in the subarray from index l to index r (inclusive).

Examples:

Input: arr[] = [1, 1, 2, 4, 3, 3]
queries[][] = [ [0, 3], [2, 5] ]
Output: 2 1
Explanation: For the query 1, the smallest element in range [0, 3] is 1, and it appears twice.
For the query 2, the smallest element in range [2, 5] is 2, and it appears once.

Input: arr[] = [1, 2, 3, 3, 1]
queries[][] = [ [0, 4], [2, 3] ]
Output: 2 2
Explanation: For the query 1, the smallest element in range [0, 4] is 1, and it appears twice.
For the query 2, the smallest element in range [2, 3] is 3, and it appears twice.

[Naive Approach] - O(n * q) Time and O(1) Space

The idea is to handle each query by finding the smallest element in the specified subarray and then counting how many times that element appears within the same range. This can be done using a straightforward method by linearly scanning the subarray for both operations.

Follow the below given steps:

  • For each query, extract the subarray from index l to r.
  • Traverse the subarray to determine the smallest element in the range.
  • Traverse the subarray again to count the frequency of this smallest element.
  • Store or print the result for each query.

Below is given the implementation:

C++
#include <bits/stdc++.h>
using namespace std;

vector<int> solveQueries(vector<int> &arr, 
    vector<vector<int>> &queries) {
    int n = arr.size();

    // to store the results
    vector<int> res;

    for(auto query:queries) {
        int l = query[0], r = query[1];

        // find smallest element in the range [l, r]
        int miny = INT_MAX;
        for(int i=l; i<=r; i++) {
            miny = min(miny, arr[i]);
        }

        // find the frequency of smallest element
        int cnt = 0;
        for(int i=l; i<=r; i++) {
            if(arr[i] == miny) {
                cnt++;
            }
        }

        // store the result
        res.push_back(cnt);
    }
    return res;
}

int main() {
    vector<int> arr = {1, 1, 2, 4, 3, 3};
    vector<vector<int>> queries = {{0, 2}, {2, 5}};
    vector<int> res = solveQueries(arr, queries);
    for(auto i:res) {
        cout << i << " ";
    }
    return 0;
}
Java
import java.util.*;

class GfG {

    public static List<Integer> solveQueries(
        List<Integer> arr, List<List<Integer>> queries) {
        int n = arr.size();

        // to store the results
        List<Integer> res = new ArrayList<>();

        for(List<Integer> query : queries) {
            int l = query.get(0), r = query.get(1);

            // find smallest element in the range [l, r]
            int miny = Integer.MAX_VALUE;
            for(int i = l; i <= r; i++) {
                miny = Math.min(miny, arr.get(i));
            }

            // find the frequency of smallest element
            int cnt = 0;
            for(int i = l; i <= r; i++) {
                if(arr.get(i) == miny) {
                    cnt++;
                }
            }

            // store the result
            res.add(cnt);
        }
        return res;
    }

    public static void main(String[] args) {
        List<Integer> arr = Arrays.asList(1, 1, 2, 4, 3, 3);
        List<List<Integer>> queries =
        Arrays.asList(Arrays.asList(0, 2), Arrays.asList(2, 5));
        List<Integer> res = solveQueries(arr, queries);
        for(int i : res) {
            System.out.print(i + " ");
        }
    }
}
Python
def solveQueries(arr, queries):
    n = len(arr)

    # to store the results
    res = []

    for query in queries:
        l, r = query[0], query[1]

        # find smallest element in the range [l, r]
        miny = float('inf')
        for i in range(l, r + 1):
            miny = min(miny, arr[i])

        # find the frequency of smallest element
        cnt = 0
        for i in range(l, r + 1):
            if arr[i] == miny:
                cnt += 1

        # store the result
        res.append(cnt)

    return res


arr = [1, 1, 2, 4, 3, 3]
queries = [[0, 2], [2, 5]]
res = solveQueries(arr, queries)
for i in res:
    print(i, end=" ")
C#
using System;
using System.Collections.Generic;

class GfG {

    public static List<int> solveQueries(
        List<int> arr, List<List<int>> queries) {
        int n = arr.Count;

        // to store the results
        List<int> res = new List<int>();

        foreach(var query in queries) {
            int l = query[0], r = query[1];

            // find smallest element in the range [l, r]
            int miny = int.MaxValue;
            for(int i = l; i <= r; i++) {
                miny = Math.Min(miny, arr[i]);
            }

            // find the frequency of smallest element
            int cnt = 0;
            for(int i = l; i <= r; i++) {
                if(arr[i] == miny) {
                    cnt++;
                }
            }

            // store the result
            res.Add(cnt);
        }
        return res;
    }

    public static void Main() {
        List<int> arr = new List<int> {1, 1, 2, 4, 3, 3};
        List<List<int>> queries = new List<List<int>> {
            new List<int> {0, 2},
            new List<int> {2, 5}
        };
        List<int> res = solveQueries(arr, queries);
        foreach(int i in res) {
            Console.Write(i + " ");
        }
    }
}
JavaScript
function solveQueries(arr, queries) {
    let n = arr.length;

    // to store the results
    let res = [];

    for(let query of queries) {
        let l = query[0], r = query[1];

        // find smallest element in the range [l, r]
        let miny = Infinity;
        for(let i = l; i <= r; i++) {
            miny = Math.min(miny, arr[i]);
        }

        // find the frequency of smallest element
        let cnt = 0;
        for(let i = l; i <= r; i++) {
            if(arr[i] === miny) {
                cnt++;
            }
        }

        // store the result
        res.push(cnt);
    }
    return res;
}

let arr = [1, 1, 2, 4, 3, 3];
let queries = [[0, 2], [2, 5]];
let res = solveQueries(arr, queries);
for(let i of res) {
    process.stdout.write(i + " ");
}

Output
2 1 

[Expected Approach] - Using Segment Tree - O(q * log n) Time and O(n) Space

The idea is to represent the array in a segment tree where each node keeps track of two values—the smallest element in its segment and how many times that element appears—so that any range query can be answered by merging only O(log n) nodes instead of scanning the entire subarray.

Follow the below given steps:

  • Build the segment tree over the array:
    • At each leaf for index i, set node.min = arr[i] and node.count = 1.
    • At each internal node, merge its left and right children:
      • If left.min < right.min, set node.min = left.min and node.count = left.count.
      • If left.min > right.min, set node.min = right.min and node.count = right.count.
      • If left.min == right.min, set node.min = left.min and node.count = left.count + right.count.
  • To answer a query [l, r]:
    • Traverse the tree to collect all nodes that exactly cover the interval [l, r].
    • Merge those nodes in the same way as above to compute the overall min and count.
  • Return the count obtained from the merged result, which is the number of occurrences of the smallest element in arr[l…r].

Below is given the implementation:

C++
#include <bits/stdc++.h>
using namespace std;

// Segment Tree Node
class Node {
public:
    // minimum value in the range
    int min; 

    // count of the minimum value in the range
    int cnt; 
};

// function to construct the tree
void buildtree(int low, int high, int pos, 
    vector<int> &arr, vector<Node*> &tree) {

    // base condition
    if (low == high) {

        // leaf Node* has arr single element
        tree[pos]->min = arr[low];
        tree[pos]->cnt = 1;
        return;
    }

    int mid = (low + high) >> 1;

    // left-subtree
    buildtree(low, mid, 2 * pos + 1, arr, tree);

    // right-subtree
    buildtree(mid + 1, high, 2 * pos + 2, arr, tree);

    // 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, vector<Node*> &tree) {
    Node* h = new Node();

    // out of range
    if (e < low or s > high) {
        h->min = h->cnt = INT_MAX;
        return h;
    }

    // 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, tree);

    // right-subtree
    Node* ans2 = query(mid + 1, e, low, high, 2 * pos + 2, tree);

    Node* ans = new Node();
    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;
}

vector<int> solveQueries(vector<int> &arr, 
    vector<vector<int>> &queries) {
    int n = arr.size();

    // create a segment tree
    vector<Node*> tree(4 * n);
    for(int i = 0; i < 4 * n; i++) {
        tree[i] = new Node();
    }

    buildtree(0, n - 1, 0, arr, tree);

    // to store the results
    vector<int> res;

    for(auto q:queries) {
        int l = q[0], r = q[1];
        int ans = query(0, n - 1, l, r, 0, tree)->cnt;
        res.push_back(ans);
    }
    return res;
}

int main() {
    vector<int> arr = {1, 1, 2, 4, 3, 3};
    vector<vector<int>> queries = {{0, 2}, {2, 5}};
    vector<int> res = solveQueries(arr, queries);
    for(auto i:res) {
        cout << i << " ";
    }
    return 0;
}
Java
import java.util.*;

class GfG {

    // Segment Tree Node
    static class Node {
        // minimum value in the range
        int min; 

        // count of the minimum value in the range
        int cnt; 
    }

    // function to construct the tree
    public static void buildtree(int low, int high, int pos, 
        List<Integer> arr, List<Node> tree) {

        // base condition
        if (low == high) {

            // leaf Node has arr single element
            tree.get(pos).min = arr.get(low);
            tree.get(pos).cnt = 1;
            return;
        }

        int mid = (low + high) >> 1;

        // left-subtree
        buildtree(low, mid, 2 * pos + 1, arr, tree);

        // right-subtree
        buildtree(mid + 1, high, 2 * pos + 2, arr, tree);

        // left subtree has the minimum element
        if (tree.get(2 * pos + 1).min < tree.get(2 * pos + 2).min) {
            tree.get(pos).min = tree.get(2 * pos + 1).min;
            tree.get(pos).cnt = tree.get(2 * pos + 1).cnt;
        }

        // right subtree has the minimum element
        else if (tree.get(2 * pos + 1).min > tree.get(2 * pos + 2).min) {
            tree.get(pos).min = tree.get(2 * pos + 2).min;
            tree.get(pos).cnt = tree.get(2 * pos + 2).cnt;
        }

        // both subtree has the same minimum element
        else {
            tree.get(pos).min = tree.get(2 * pos + 1).min;
            tree.get(pos).cnt = tree.get(2 * pos + 1).cnt + tree.get(2 * pos + 2).cnt;
        }
    }

    // function that answers every query
    public static Node query(int s, int e, int low, int high, int pos, List<Node> tree) {
        Node h = new Node();

        // out of range
        if (e < low || s > high) {
            h.min = h.cnt = Integer.MAX_VALUE;
            return h;
        }

        // in range
        if (s >= low && e <= high) {
            return tree.get(pos);
        }

        int mid = (s + e) >> 1;

        // left-subtree
        Node ans1 = query(s, mid, low, high, 2 * pos + 1, tree);

        // right-subtree
        Node ans2 = query(mid + 1, e, low, high, 2 * pos + 2, tree);

        Node ans = new Node();
        ans.min = Math.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;
    }

    public static List<Integer> solveQueries(List<Integer> arr, 
        List<List<Integer>> queries) {
        int n = arr.size();

        // create a segment tree
        List<Node> tree = new ArrayList<>();
        for(int i = 0; i < 4 * n; i++) {
            tree.add(new Node());
        }

        buildtree(0, n - 1, 0, arr, tree);

        // to store the results
        List<Integer> res = new ArrayList<>();

        for(List<Integer> q : queries) {
            int l = q.get(0), r = q.get(1);
            int ans = query(0, n - 1, l, r, 0, tree).cnt;
            res.add(ans);
        }
        return res;
    }

    public static void main(String[] args) {
        List<Integer> arr = Arrays.asList(1, 1, 2, 4, 3, 3);
        List<List<Integer>> queries = Arrays.asList(Arrays.asList(0, 2), Arrays.asList(2, 5));
        List<Integer> res = solveQueries(arr, queries);
        for(int i : res) {
            System.out.print(i + " ");
        }
    }
}
Python
# Segment Tree Node
class Node:
    # minimum value in the range
    def __init__(self):
        self.min = None

    # count of the minimum value in the range
        self.cnt = None

# function to construct the tree
def buildtree(low, high, pos, arr, tree):

    # base condition
    if low == high:

        # leaf Node has arr single element
        tree[pos].min = arr[low]
        tree[pos].cnt = 1
        return

    mid = (low + high) >> 1

    # left-subtree
    buildtree(low, mid, 2 * pos + 1, arr, tree)

    # right-subtree
    buildtree(mid + 1, high, 2 * pos + 2, arr, tree)

    # 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
    elif 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
def query(s, e, low, high, pos, tree):
    h = Node()

    # out of range
    if e < low or s > high:
        h.min = h.cnt = float('inf')
        return h

    # in range
    if s >= low and e <= high:
        return tree[pos]

    mid = (s + e) >> 1

    # left-subtree
    ans1 = query(s, mid, low, high, 2 * pos + 1, tree)

    # right-subtree
    ans2 = query(mid + 1, e, low, high, 2 * pos + 2, tree)

    ans = Node()
    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
    elif ans1.min < ans2.min:
        ans.cnt = ans1.cnt

    else:
        ans.cnt = ans2.cnt

    return ans

def solveQueries(arr, queries):
    n = len(arr)

    # create a segment tree
    tree = [Node() for _ in range(4 * n)]

    buildtree(0, n - 1, 0, arr, tree)

    # to store the results
    res = []

    for q in queries:
        l, r = q[0], q[1]
        ans = query(0, n - 1, l, r, 0, tree).cnt
        res.append(ans)
    return res

if __name__ == "__main__":
    arr = [1, 1, 2, 4, 3, 3]
    queries = [[0, 2], [2, 5]]
    res = solveQueries(arr, queries)
    for i in res:
        print(i, end=" ")
C#
using System;
using System.Collections.Generic;

class GfG {

    // Segment Tree Node
    public class Node {
        // minimum value in the range
        public int min;

        // count of the minimum value in the range
        public int cnt;
    }

    // function to construct the tree
    public static void buildtree(int low, int high, int pos, 
        List<int> arr, List<Node> tree) {

        // base condition
        if (low == high) {

            // leaf Node has arr single element
            tree[pos].min = arr[low];
            tree[pos].cnt = 1;
            return;
        }

        int mid = (low + high) >> 1;

        // left-subtree
        buildtree(low, mid, 2 * pos + 1, arr, tree);

        // right-subtree
        buildtree(mid + 1, high, 2 * pos + 2, arr, tree);

        // 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
    public static Node query(int s, int e, int low, int high, int pos, List<Node> tree) {
        Node h = new Node();

        // out of range
        if (e < low || s > high) {
            h.min = h.cnt = int.MaxValue;
            return h;
        }

        // in range
        if (s >= low && e <= high) {
            return tree[pos];
        }

        int mid = (s + e) >> 1;

        // left-subtree
        Node ans1 = query(s, mid, low, high, 2 * pos + 1, tree);

        // right-subtree
        Node ans2 = query(mid + 1, e, low, high, 2 * pos + 2, tree);

        Node ans = new Node();
        ans.min = Math.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;
    }

    public static List<int> solveQueries(List<int> arr, 
        List<List<int>> queries) {
        int n = arr.Count;

        // create a segment tree
        List<Node> tree = new List<Node>();
        for (int i = 0; i < 4 * n; i++) {
            tree.Add(new Node());
        }

        buildtree(0, n - 1, 0, arr, tree);

        // to store the results
        List<int> res = new List<int>();

        foreach (var q in queries) {
            int l = q[0], r = q[1];
            int ans = query(0, n - 1, l, r, 0, tree).cnt;
            res.Add(ans);
        }
        return res;
    }

    public static void Main() {
        List<int> arr = new List<int> {1, 1, 2, 4, 3, 3};
        List<List<int>> queries = new List<List<int>> {
            new List<int> {0, 2},
            new List<int> {2, 5}
        };
        List<int> res = solveQueries(arr, queries);
        foreach (int i in res) {
            Console.Write(i + " ");
        }
    }
}
JavaScript
// Segment Tree Node
class Node {

    // minimum value in the range
    // count of the minimum value in the range
}

// function to construct the tree
function buildtree(low, high, pos, arr, tree) {
    // base condition
    if (low === high) {

        // leaf Node has arr single element
        tree[pos].min = arr[low];
        tree[pos].cnt = 1;
        return;
    }

    let mid = (low + high) >> 1;

    // left-subtree
    buildtree(low, mid, 2 * pos + 1, arr, tree);

    // right-subtree
    buildtree(mid + 1, high, 2 * pos + 2, arr, tree);

    // 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
function query(s, e, low, high, pos, tree) {
    let h = new Node();

    // out of range
    if (e < low || s > high) {
        h.min = h.cnt = Number.MAX_SAFE_INTEGER;
        return h;
    }

    // in range
    if (s >= low && e <= high) {
        return tree[pos];
    }

    let mid = (s + e) >> 1;

    // left-subtree
    let ans1 = query(s, mid, low, high, 2 * pos + 1, tree);

    // right-subtree
    let ans2 = query(mid + 1, e, low, high, 2 * pos + 2, tree);

    let ans = new Node();
    ans.min = Math.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 solveQueries(arr, queries) {
    let n = arr.length;

    // create a segment tree
    let tree = [];
    for (let i = 0; i < 4 * n; i++) {
        tree[i] = new Node();
    }

    buildtree(0, n - 1, 0, arr, tree);

    // to store the results
    let res = [];

    for (let q of queries) {
        let l = q[0], r = q[1];
        let ans = query(0, n - 1, l, r, 0, tree).cnt;
        res.push(ans);
    }
    return res;
}

let arr = [1, 1, 2, 4, 3, 3];
let queries = [[0, 2], [2, 5]];
let res = solveQueries(arr, queries);
for (let i of res) {
    process.stdout.write(i + " ");
}

Output
2 1 

Next Article

Similar Reads