Segment Tree | Range Minimum Query


Segment Tree − A segment tree is a tree data structure used for storing intervals and segments. It is a static structure, i.e. it cannot be modified once it is built. Segment trees are used to handle range queries on an array or a similar linear data structure.

In a segment tree, we divide an input array into segments and precompute the values for these segments. Each node in a segment tree depicts an interval or segment of the array. The root node represents the entire array and each child node represents the segments formed by dividing the parent node. This division leads to representing the leaf nodes as individual elements of the array.

Segment Tree for Range of Sum queries −

Original Array: [7, 1, 2, 3, 6, 5, 0, 4]
Segment Tree:
         38
       /    \
      13     25
     / \     / \
    8   5   11   4
   / \ / \  / \ / \
  7  1 2  3 6  5 0 4

Segment Tree has a complexity of O(logN) for each range query and update operation.

Range Minimum Query − RMQ is a common problem where for a given array, we need to find the minimum element in a range specified. Segment Tree is the most efficient data structure used for the problem.

Problem Statement

Given an array of integers arr[] containing N elements along with start and end index. The task is to find the minimum element among the elements lying in the range [start, end].

Sample Example 1

Input

N = 8
arr[] = {1, 7, 8, 9, 5, 2, 3, 4}
start = 2
end = 6

Output

2

Explanation

Array within the specified range is: {8, 9, 5, 2, 3}

In the given range, 2 is the minimum element.

Sample Example 2

Input

N = 3
arr[] = {1, 3, 2}
start = 1
end = 1

Output

3

Explanation

Array within the specified range is: {3}

In the given range, 3 is the minimum element.

Solution Approach

The Range Minimum Query problem can be solved by following the following steps −

  • Construct a segment tree for the input array.

  • Recursively find the segment of the tree contained in the query. Each segment can be categorised as one of the following −

    • Complete Overlap − Current segment is completely within the query range.

    • No Overlap − Current segment is completely outside the query range.

    • Partial Overlap − Current segment partially covers the query range.

Pseudocode to Construct Segment Tree

function segmentTreeUtil(arr, seg_start, seg_end, tree, curr)
   if seg_start == seg_end then
      tree[curr] = arr[seg_start]
      return arr[seg_start]

   mid = getMid(seg_start, seg_end)
   tree[curr] = minVal(segmentTreeUtil(arr, seg_start, mid, tree, curr * 2 + 1), segmentTreeUtil(arr, mid + 1, seg_end, tree, curr * 2 + 2))
   return tree[curr]
end function

function segmentTree(arr, n)
   x = ceil(log2(n))
   max_size = 2 * (2^x) - 1
   tree = new int[max_size]
   segmentTreeUtil(arr, 0, n - 1, tree, 0)
   return tree
end function

Pseudocode for RMQ

function RMQUtil(tree, seg_start, seg_end, start, end, index)
   if start <= seg_start and end >= seg_end then
      return tree[index]    
   if seg_end < start or seg_start > end then
      return INT_MAX
end function

   mid = getMid(seg_start, seg_end)
   return minVal(RMQUtil(tree, seg_start, mid, start, end, 2 * index + 1), RMQUtil(tree, mid + 1, seg_end, start, end, 2 * index + 2))

function RMQ(tree, n, start, end)
   if start < 0 or end > n - 1 or start > end then
      print "Query Range Invalid"
      return -1
   return RMQUtil(tree, 0, n - 1, start, end, 0)
end function

Example: C++ Implementation

The following code constructs a segment tree to solve the RMQ problem.

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

int minVal(int x, int y){
   return (x < y) ? x : y;
}
int getMid(int x, int y){
   return x + (y - x) / 2;
}
// Recursive function used to find the minimum element in the query range
int RMQUtil(int *tree, int seg_start, int seg_end, int start, int end, int index){
   // Complete Overlap
   if (start <= seg_start && end >= seg_end)
      return tree[index];
   // No Overlap
   if (seg_end < start || seg_start > end)
      return INT_MAX;
   // Partial Overlap
   int mid = getMid(seg_start, seg_end);
   return minVal(RMQUtil(tree, seg_start, mid, start, end, 2 * index + 1), RMQUtil(tree, mid + 1, seg_end, start, end, 2 * index + 2));
}
// Calculates RMQ by calling RMQUtil()
int RMQ(int *tree, int n, int start, int end){
   if (start < 0 || end > n - 1 || start > end){
      cout << "Query Range Invalid";
      return -1;
   }
   return RMQUtil(tree, 0, n - 1, start, end, 0);
}
// Creates Segment Tree for input array
int segmentTreeUtil(int arr[], int seg_start, int seg_end, int *tree, int curr){
   // Base Case of only one element in array
   if (seg_start == seg_end)    {
      tree[curr] = arr[seg_start];
      return arr[seg_start];
   }
   // Dividing array into segments
   int mid = getMid(seg_start, seg_end);
   tree[curr] = minVal(segmentTreeUtil(arr, seg_start, mid, tree, curr * 2 + 1), segmentTreeUtil(arr, mid + 1, seg_end, tree, curr * 2 + 2));
   return tree[curr];
}
// Creates Segment Tree by allocating memmory and calling segmentTreeUtil()
int *segmentTree(int arr[], int n){
   int x = (int)(ceil(log2(n)));
   int max_size = 2 * (int)pow(2, x) - 1;
   int *tree = new int[max_size];
   segmentTreeUtil(arr, 0, n - 1, tree, 0);
   return tree;
}
int main(){
   int arr[] = {1, 7, 8, 9, 5, 2, 3, 4};
   int n = 8;
   int *tree = segmentTree(arr, n);
   int start = 2;
   int end = 6;
   cout << "Minimum value = " << RMQ(tree, n, start, end) << endl;
   return 0;
}

Output

Minimum value = 2

Time Complexity − The time complexity for building the tree is O(N) and the time complexity for each RMQ is O(logn). Thus, for Q queries, the time complexity is O(Q*logN).

Space Complexity − O(N)

Conclusion

In conclusion, the Range Minimum Query (RMQ) using the Segment Tree is an efficient data structure and algorithm for finding the minimum element in a given range of an array. The time complexity of each query is O(logN) which is better than the naive approach to iterate over the array having a complexity of O(N).

Updated on: 03-Nov-2023

291 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements