题意
思路
- dp(i,j) 表示[i, i+2^j]区间内的最小值
- dp(i,j) = min(dp(i, j-1), dp(i+2^(j-1), j-1) )
- 查询[l,r]时,len = log2(l-r),min(dp(l, len),dp(r-(2^len), len) )
实现
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e6;
int a[maxn];
int dp[maxn][21];
int n,q;
void st(){
for (int i=0;i<n-1;i++){
if (a[i] <= a[i+1]){
dp[i][0] = i;
}
else{
dp[i][0] = i+1;
}
}
for (int j=1;j<=20;j++){
for (int i=0;i+(1<<j)<n;i++){
if (a[dp[i][j-1]] <= a[dp[i+(1<<(j-1))][j-1]]){
dp[i][j] = dp[i][j-1];
}
else{
dp[i][j] = dp[i+(1<<(j-1))][j-1];
}
}
}
}
int log2(int x){
int ret = -1;
while(x > 0){
x >>= 1;
ret++;
}
return ret;
}
int ask(int l,int r){
int len = r - l;
len = log2(len);
if(len == -1)
return l;
if (a[dp[l][len]] <= a[dp[r-(1<<len)][len]]){
return dp[l][len];
}
else{
return dp[r-(1<<len)][len];
}
}
int main(){
cin>>n;
for (int i=0;i<n;i++){
scanf("%d",&a[i]);
}
st();
cin>>q;
for (int t=0;t<q;t++){
int l,r;
scanf("%d%d",&l,&r);
cout << a[ask(l-1,r-1)] << "\n";
}
return 0;
}