//se foloseste segment tree
//am citit https://www.geeksforgeeks.org/segment-tree-set-1-range-minimum-query/
#include <bits/stdc++.h>
using namespace std;
ifstream f("rmq.in");
ofstream g("rmq.out");
int mini(int x, int y)
{ if(x<y)
return x;
else
return y;
}
// A utility function to get the
// middle index from corner indexes.
int getMid(int left, int right)
{
return left+(right-left)/2;
}
/* A recursive function to get the
minimum value in a given range
of array indexes. The following
are parameters for this function.
st --> Pointer to segment tree
index --> Index of current node in the
segment tree. Initially 0 is
passed as root is always at index 0
ss & se --> Starting and ending indexes
of the segment represented
by current node, i.e., st[index]
qs & qe --> Starting and ending indexes of query range */
int RMQUtil(int *st, int ss, int se, int qs, int qe, int index)
{
// If segment of this node is a part
// of given range, then return
// the min of the segment
if (qs <= ss && qe >= se)
return st[index];
// If segment of this node
// is outside the given range
if (se < qs || ss > qe)
return INT_MAX;
// If a part of this segment
// overlaps with the given range
int mid = getMid(ss, se);
return mini(RMQUtil(st, ss, mid, qs, qe, 2*index+1),RMQUtil(st, mid+1, se, qs, qe, 2*index+2));
}
// Return minimum of elements in range
// from index qs (query start) to
// qe (query end). It mainly uses RMQUtil()
int RMQ(int *st, int n, int qs, int qe)
{
// Check for erroneous input values
if (qs < 0 || qe > n-1 || qs > qe)
{
cout<<"Invalid Input";
return -1;
}
return RMQUtil(st, 0, n-1, qs, qe, 0);
}
// A recursive function that constructs
// Segment Tree for array[ss..se].
// si is index of current node in segment tree st
int constructSTUtil(int arr[], int ss, int se,
int *st, int si)
{
// If there is one element in array,
// store it in current node of
// segment tree and return
if (ss == se)
{
st[si] = arr[ss];
return arr[ss];
}
// If there are more than one elements,
// then recur for left and right subtrees
// and store the minimum of two values in this node
int mid = getMid(ss, se);
st[si] = mini(constructSTUtil(arr, ss, mid, st, si*2+1),
constructSTUtil(arr, mid+1, se, st, si*2+2));
return st[si];
}
/* Function to construct segment tree
from given array. This function allocates
memory for segment tree and calls constructSTUtil() to
fill the allocated memory */
int *constructST(int arr[], int n)
{
// Allocate memory for segment tree
//Height of segment tree
int x = (int)(ceil(log2(n)));
// Maximum size of segment tree
int max_size = 2*(int)pow(2, x) - 1;
int *st = new int[max_size];
// Fill the allocated memory st
constructSTUtil(arr, 0, n-1, st, 0);
// Return the constructed segment tree
return st;
}
int main()
{
int arr[100001],n,m,i,qs,qe;
f>>n>>m;
for(i=0;i<n;i++)
{
f>>arr[i];
}
// Build segment tree from given array
int *st = constructST(arr, n);
for(i=0;i<m;i++)
{
f>>qs>>qe;
// Starting index of query range
// Ending index of query range
g<<RMQ(st, n, qs-1, qe-1)<<'\n';
// Print minimum value in arr[qs..qe]
}
return 0;
}