- dp[i][j] 表示区间 [i,i+2j) 的最小值
- dp[i][j]=min(dp[i][j−1],dp[i+2j−1][j−1]
- 对于询问
[le,ri]
,令
len=ri−le+1
,再令
2lb≤len<2lb+1
,则
min[le,ri]=min{dp[le][lb],dp[ri−2lb+1][lb]}
/* **********************************************
File Name: 1068.cpp
Auther: zhengdongjian@tju.edu.cn
Created Time: 2015/9/25 星期五 下午 9:19:08
*********************************************** */
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int MAX = 1000007;
const int MAX_L = 21;
int dp[MAX][MAX_L];
int a[MAX];
int po[MAX_L];
int main() {
po[0] = 1;
for (int i = 1; i < MAX_L; ++i) {
po[i] = po[i - 1] << 1;
}
int n;
scanf(" %d", &n);
for (int i = 1; i <= n; ++i) {
scanf(" %d", a + i);
}
for (int i = n; i >= 1; --i) {
dp[i][0] = a[i];
for (int j = 1; i + (1 << j) <= n + 1; ++j) {
//[i, i + (1 << j))
//[i, i + (1 << (j - 1))) | [i + (1 << (j - 1)), i + (1 << j))
//=>
//dp[i][j - 1] | dp[i + (1 << (j - 1))][j - 1]
dp[i][j] = min(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
//printf("dp[%d][%d] = %d\n", i, j, dp[i][j]);
}
}
int m;
scanf(" %d", &m);
while (m--) {
int le, ri;
scanf(" %d %d", &le, &ri);
int lb = upper_bound(po, po + MAX_L, ri - le + 1) - po - 1;
//printf("lb = %d\n", lb);
//printf("cut to dp[%d][%d] and dp[%d][%d]\n", le, lb, ri - po[lb] + 1, lb);
printf("%d\n", min(dp[le][lb], dp[ri - po[lb] + 1][lb]));
}
return 0;
}