//// C++ program to do range
//// minimum query in O(1) time with
//// O(n*n) extra space and O(n*n)
//// preprocessing time.
//#include <bits/stdc++.h>
//using namespace std;
//
//#define MAX 500
//
//#include <fstream>
//ifstream f("rmq.in");
//ofstream g("rmq.out");
//
//// lookup[i][j] is going to store
//// index of minimum value in
//// arr[i..j]
//int lookup[MAX][MAX];
//
//// Structure to represent a query range
//struct Query {
// int L, R;
//}q[1000];
//
//// Fills lookup array lookup[n][n]
//// for all possible values
//// of query ranges
//void preprocess(int arr[], int n)
//{
// // Initialize lookup[][] for the
// // intervals with length 1
// for (int i = 1; i <= n; i++)
// lookup[i][i] = i;
//
// // Fill rest of the entries in bottom up manner
// for (int i = 1; i <= n; i++) {
// for (int j = i + 1; j <= n; j++)
//
// // To find minimum of [0,4],
// // we compare minimum
// // of arr[lookup[0][3]] with arr[4].
// if (arr[lookup[i][j - 1]] < arr[j])
// lookup[i][j] = lookup[i][j - 1];
// else
// lookup[i][j] = j;
// }
//}
//
//// Prints minimum of given m
//// query ranges in arr[0..n-1]
//void RMQ(int arr[], int n, Query q[], int m)
//{
// // Fill lookup table for
// // all possible input queries
// preprocess(arr, n);
//
// // One by one compute sum of all queries
// for (int i = 0; i < m; i++)
// {
// // Left and right boundaries
// // of current range
// int L = q[i].L, R = q[i].R;
//
// // Print sum of current query range
// g << arr[lookup[L][R]] << endl;
// }
//}
//
//// Driver code
//int main()
//{
//// int a[] = { 7, 2, 3, 0, 5, 10, 3, 12, 18 };
//// int n = sizeof(a) / sizeof(a[0]);
//// Query q[] = { { 2, 4 }, { 1, 2 }, { 3, 5 }, { 1, 4 } };
//// int m = sizeof(q) / sizeof(q[0]);
//// RMQ(a, n, q, m);
// int N,M,v[1000];
//// Query q;
// f>>N>>M;
//
// for (int i = 1; i <= N; ++i) {
// f>>v[i];
// }
//
// for (int i = 0; i < M; ++i) {
// f>>q[i].L>>q[i].R;
// }
// f.close();
// RMQ(v,N,q,M);
//// cout<<"am citit";
// return 0;
//}
#include <iostream>
#include <fstream>
#include <math.h>
using namespace std;
ifstream in("rmq.in");
ofstream out("rmq.out");
int v[100100], bucketMinPoz[100100][20], k, i, j, n, m, x, y, p; //retinem poz minimului din v in bucketul actual
void creeazaBucketuri()
{
for(i = 0; i < n ; i++)
bucketMinPoz[i][0] = i;
for(j = 1; (1 << j) <= n; j++)
for(i = 0; i + (1 << j) - 1 < n; i++)
if(v[bucketMinPoz[i][j - 1]] < v[bucketMinPoz[i + (1 << (j - 1))][j - 1]])
bucketMinPoz[i][j] = bucketMinPoz[i][j - 1];
else
bucketMinPoz[i][j] = bucketMinPoz[i + (1 << (j - 1))][j - 1];
}
int main()
{
in>>n>>m;
for(i = 0; i < n; i++)
in>>v[i];
creeazaBucketuri();
for(i = 1; i <= m; i++)
{
in>>x>>y;
p = 1;
k = 0;
while(p * 2 <= y - x + 1) //k = log(j - i + 1)
{
p *= 2;
k++;
}
if(v[bucketMinPoz[x - 1][k]] <= v[bucketMinPoz[y - p][k]])
out<<v[bucketMinPoz[x - 1][k]]<<'\n';
else
out<<v[bucketMinPoz[y - p][k]]<<'\n';
}
return 0;
}