Min-Max Range Queries in Array in C++

Given an array Arr[] containing N elements. The goal is to find the minimum and maximum value from indexes of query.
According to the query we are given starting index and ending indexes.
In − Arr[] = { 1, 2, 3, 4, 5 } QStart = 1 QEnd = 4
Out −
Minimum Value : 2
Maximum Value : 5
Explanation −In the above queries the starting index is 1 and ending index is 4. Between these two indexes, minimum value in Arr is 2 and maximum value is 5
In − Arr[] = { 10, 12, 3, 2, 5, 18 } QStart = 2 QEnd = 5
Out −
Minimum Value : 2
Maximum Value : 18
Explanation − In the above queries the starting index is 2 and ending index is 5. Between these two indexes, minimum value in Arr is 2 and maximum value is 18
In this approach we will use segment trees for the range lpos to rpos to find the minimum and maximum values in the given query range.
Take the input array Arr[] and query indexes QStart and QEnd.
Take the input array Arr[] and query indexes QStart and QEnd.
Take the result of type value.
Take the result of type value.
Structure value is used to store minimum and maximum value found in an array using a given query.
Structure value is used to store minimum and maximum value found in an array using a given query.
Structure value is used to store minimum and maximum value found in an array using a given query.
Structure value is used to store minimum and maximum value found in an array using a given query.
Function minMax(struct value *root1, int num, int qStart1, int qEnd1) takes query indexes and finds minimum and maximum in an array between index range qStart1 and qEnd1.
Function minMax(struct value *root1, int num, int qStart1, int qEnd1) takes query indexes and finds minimum and maximum in an array between index range qStart1 and qEnd1.
Check if ( qStart1 < 0 OR qEnd1 > num-1 OR qStart1 > qEnd1 ). If true then input range in the query is invalid.
Check if ( qStart1 < 0 OR qEnd1 > num-1 OR qStart1 > qEnd1 ). If true then input range in the query is invalid.
Otherwise, call minmaxFind(root1, 0, num-1, qStart1, qEnd1, 0).
Otherwise, call minmaxFind(root1, 0, num-1, qStart1, qEnd1, 0).
Function minmaxFind(struct value *root, int startT, int endT, int qStart, int qEnd, int pos) is a recursive function. It takes a pointer to segment tree- root, starting and ending index of current value as startT and endT.
Function minmaxFind(struct value *root, int startT, int endT, int qStart, int qEnd, int pos) is a recursive function. It takes a pointer to segment tree- root, starting and ending index of current value as startT and endT.
It also takes a starting and ending index in query range. The current index of value in the segment tree has index pos.
It also takes a starting and ending index in query range. The current index of value in the segment tree has index pos.
If (qStart <= startT) AND if( qEnd >= endT) then the segment of current value is part of the given range. So return minimum and maximum in that value.
If (qStart <= startT) AND if( qEnd >= endT) then the segment of current value is part of the given range. So return minimum and maximum in that value.
If it is outside the range then update the current value with minVal and maxVal.
If it is outside the range then update the current value with minVal and maxVal.
If current part overlaps with given range then :-
If current part overlaps with given range then :-
Take middl = startT + ( endT - startT )/2.
Take middl = startT + ( endT - startT )/2.
Take p1 and p2 as 2*pos+1 and =2*pos+2.
Take p1 and p2 as 2*pos+1 and =2*pos+2.
Update lpos as lpos = minmaxFind(root, startT, middl, qStart, qEnd, p1) and rpos as minmaxFind(root, middl+1, endT, qStart, qEnd, p2).
Update lpos as lpos = minmaxFind(root, startT, middl, qStart, qEnd, p1) and rpos as minmaxFind(root, middl+1, endT, qStart, qEnd, p2).
Set temp.minVal as minimum of lpos.minVal and rpos.minVal.
Set temp.minVal as minimum of lpos.minVal and rpos.minVal.
Set temp.maxVal as maximum of lpos.maxVal and rpos.maxVal.
Set temp.maxVal as maximum of lpos.maxVal and rpos.maxVal.
Return temp.
Return temp.
Function segmentTree(int arr2[], int startT2, int endT2, struct value *root2, int pos2) is used to construct a segment tree for array arr2[] with index range as startT2 and endT2 and current value position is pos2.
Function segmentTree(int arr2[], int startT2, int endT2, struct value *root2, int pos2) is used to construct a segment tree for array arr2[] with index range as startT2 and endT2 and current value position is pos2.
Function *createTree(int arr0[], int num0) is used to construct a segment tree from a given array arr0. This function allocates memory for segment trees and calls segmentTree() for memory allocation.
Function *createTree(int arr0[], int num0) is used to construct a segment tree from a given array arr0. This function allocates memory for segment trees and calls segmentTree() for memory allocation.
#include<bits/stdc++.h>
using namespace std;
struct value{
   int minVal;
   int maxVal;
};
struct value minmaxFind(struct value *root, int startT, int endT, int qStart,
   int qEnd, int pos){
   struct value temp, lpos ,rpos;
   if (qStart <= startT) {
      if( qEnd >= endT)
         { return root[pos]; }
   }
   if (endT < qStart || startT > qEnd) {
      temp.minVal = 9999;
      temp.maxVal = -9999;
      return temp;
   }
   int middl = startT + ( endT - startT )/2;
   int p1=2*pos+1;
   int p2=2*pos+2;
   lpos = minmaxFind(root, startT, middl, qStart, qEnd, p1);
   rpos = minmaxFind(root, middl+1, endT, qStart, qEnd, p2);
   temp.minVal = (lpos.minVal<rpos.minVal) ? lpos.minVal : rpos.minVal ;
   temp.maxVal = (lpos.maxVal>rpos.maxVal) ? lpos.maxVal : rpos.maxVal ;
   return temp;
}
struct value minMax(struct value *root1, int num, int qStart1, int qEnd1){
   struct value temp1;
   if (qStart1 < 0 || qEnd1 > num-1 || qStart1 > qEnd1){
      cout<<"Please enter Valid input!!";
      temp1.minVal = 9999;
      temp1.maxVal = -9999;
      return temp1;
   }
   return minmaxFind(root1, 0, num-1, qStart1, qEnd1, 0);
}
void segmentTree(int arr2[], int startT2, int endT2, struct value *root2, int pos2){ 
   if (startT2 == endT2) { 
      root2[pos2].minVal = arr2[startT2];
      root2[pos2].maxVal = arr2[startT2];
      return ;
   }
   int p1=pos2*2+1;   
   int p2=pos2*2+2;
   int middl2 = startT2+(endT2-startT2)/2;
   segmentTree(arr2, startT2, middl2, root2, p1);
   segmentTree(arr2, middl2+1, endT2, root2, p2);
   root2[pos2].minVal = root2[p1].minVal<root2[p2].minVal ? root2[p1].minVal : root2[p2].minVal;
   root2[pos2].maxVal = root2[p1].maxVal>root2[p2].maxVal ? root2[p1].maxVal : root2[p2].maxVal;
}
struct value *createTree(int arr0[], int num0) { 
   int height = (int)(ceil(log2(num0)));
   int maxS = 2*(int)pow(2, height) - 1;
   struct value *root0 = new struct value[maxS];
   segmentTree(arr0, 0, num0-1, root0, 0);
   return root0;
}
int main() { 
   int Arr[] = { 1, 2, 3, 4, 5 };
   int length = sizeof(Arr)/sizeof(Arr[0]);
   struct value *tree = createTree(Arr, length);
   int QStart = 1;
   int QEnd = 4;
   struct value answer=minMax(tree, length, QStart, QEnd);
   cout<<"Minimum Value : "<<answer.minVal<<endl;
   cout<<"Maximum Value : "<<answer.maxVal;
   return 0;
}
If we run the above code it will generate the following Output
Minimum Value : 2
Maximum Value : 5