## Range Minimum Query

**RANGE QUERY**

Given a (big) array r[0..n-1], and a lot of queries of certain type. We may want to pre-process the data so that each query can be performed fast. In this section, we use T (f, g) to denote the running time for an algorithm is O(f(n)) for pre-processing, and O(g(n)) for each query.

If the queries are of type getsum(a, b), which asks the sum of all the elements between a and b, inclusive, we have a T (n, 1) algorithm: Compute s[i] to be the sum from r[0] to r[i-1], inclusive, then getsum(a,b) simply returns s[b+1]-s[a].

**RANGE MINIMUM QUERY**

For the queries of the form getmin(a,b) asks the minimum elements between r[a] and r[b], inclusive, the task is little more hard. The idea is always to get the min in some big ranges, so in the queries we may try to use these big ranges to compute fast. One simple algorithm is T (n,sqrt(n)): Break the n numbers into sqrt(n) regions, each of size sqrt(n). Compute the champion for each region. For each query getmin(a,b), we go from a towards right to the nearest station (at most sqrt(n) steps), then go by at most sqrt(n) stations (big regions) to the nearest station before b, and from there go to b.

**Sparse Table (ST) Algorithm**

A better approach is to preprocess **RMQ** for sub arrays of length **2 ^{k} **using dynamic programming. We will keep an array

**preProcess[0, N-1][0, logN]**where

**preProcess[i][j]**is the index of the minimum value in the sub array starting at

**i**having length

**2**. For example :

^{j}A[0] | A[1] | A[2] | A[3] | A[4] | A[5] |

2 | 4 | 3 | 1 | 6 | 7 |

For the above array the preProcess[1][0] = 1, preProcess[1][1]=2,preProcess[1][2]=3 and so on. Specifically, we find the minimum in a block of size *2*^{j} by comparing the two minima of its two constituent blocks of size *2*^{j-1}. More formally, preProcess[i, j] = preProcess[i, j -1] if A[preProcess[i, j -1]] <= A[preProcess[i+*2*^{j-1}, j -1]] and preProcess[i, j] = preProcess[i+*2*^{j-1}, j -1] otherwise.

Once we have these values preprocessed, let’s show how we can use them to calculate RMQ(i, j). The idea is to select two blocks that entirely cover the interval [i..j] and find the minimum between them. We select two overlapping blocks that entirely cover the subrange: let 2k be the size of the largest block that fits into the range from i to j, that is let k = log(j – i). Then rmq(i, j) can be computed by comparing the minima of the following two blocks: i to i + *2*^{k} – 1 (preProcess(i, k)) and j – *2*^{k} + 1 to j (preProcess(j –*2*^{k} +1, k)). These values have already been computed, so we can find the RMQ in constant time.

So as shown above if we need to calculate minimum between A[1] and A[5] we will take two sections of size 4 and compare their minimum values to get the answer. Below is a C++ template class implementation :

int preProcess[1000][10]; template class RMQMin { T *A; public: RMQMin(int N,T *array):A(array) { int i,j; for (i=0;i<N;i++) preProcess[i][0]=i; for (j=1; (1<<j)<=N; j++) for (i=0; i+(1<<j)-1<N; i++) preProcess[i][j]= A[preProcess[i][j-1]]<= A[preProcess[i+(1<<(j-1))][j-1]]? preProcess[i][j-1] :preProcess[i+(1<<(j-1))][j-1]; } int query(int start,int end) { int diff=end-start; diff=31 - __builtin_clz(diff+1); return A[preProcess[start][diff]] <=A[preProcess[end-(1<<diff)+1][diff]]? preProcess[start][diff] :preProcess[end-(1<<diff)+1][diff]; } };

You can simply use the above class for any type of variable(numeric ofcourse). Just keep in mind that you have to declare a preProcess array of size N x log N . So it turns out that the space complexity of the algorithm is **O(N log N)** and time complexity **T(NlogN, 1)**.

-fR0D

>> Compute s[i] to be the sum from r[0] to r[i-1], inclusive, then getsum(a,b) simply returns s[a+1]-s[b]

Looks like you mean it should return s[b+1]-s[a].

AntonAugust 12, 2010 at 12:29 PM

Yes. Thanks.

fR0DDYAugust 12, 2010 at 2:35 PM

you mention “preProcess[1][0] = 1” and a couple of words later “preProcess[1][0] = 3”. The second time i think you meant “preProcess[3][0]”

st0leApril 6, 2011 at 10:15 AM

Hi,

It was meant to be preProcess[1][2]=3. I have corrected it.

fR0DDYApril 6, 2011 at 8:13 PM

hi, how can we use this concept to find the maximum element in a range?

pranayJune 2, 2011 at 11:17 PM

You just need to change some sign to find the maximum element. Try to figure out the algorithm and then you can see how to find the maximum element in a range.

fR0DDYJune 4, 2011 at 11:12 AM

plzzz add some tut on binary indexed tree….

aayushJune 9, 2011 at 4:51 PM

Nothing personal..am just curious!!!

Why do I read your post that solves the problem with O(NlogN) time and needs additional memory of O(NlogN) instead of doing a simple linear search in O(N) time and with no memory overhead.

pseudo code for linear search RMQ[A, i, j]:

minPos=i, minVal=A[i]

for each k i+1 to j

if A[k]< minVal

set minPos =k and minVal=A[k]

end-if

end-for

kausikNovember 16, 2012 at 4:04 PM

Think about the case where the number of queries are very large. Your algorithm will take O(N) time for each query while the algorithm described above will take only O(1) time for each query.

fR0DDYNovember 16, 2012 at 4:31 PM

thanks fR0DDY

kausikNovember 17, 2012 at 8:18 AM

What if we have more than 10^9 elements in array ?

bit_cracker007December 10, 2012 at 12:23 PM

hey can you help me on this

what if i have to update the array

how will i reflect in the table then??

Aman ChoudharyMarch 30, 2013 at 12:54 AM

why this 31-(r-l+1)

Kunal PrinceFebruary 6, 2016 at 9:36 PM