用F[ i ][ j ]表示从 i 开始 1<<j 个位置中的最小值,在LCA等中也可以表示位置。
递推方程是显然的。
由于最值有重叠求值不影响的特点,所以询问[i,j]的答案是max( f [ i ] [ k ] , f [ j - ( 1 << k ) + 1 ] [ k ] ),其中k = log ( j - i + 1 ) / log ( 2 )。
代码如下:
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int f[10000][20];
int main()
{
int n,q;
cin>>n;
for(int i=1;i<=n;i++) cin>>f[i][0];
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
cin>>q;
while(q--)
{
int i,j,k;
cin>>i>>j;
k=log(j-i+1)/log(2);
cout<<max(f[i][k],f[j-(1<<k)+1][k])<<endl;
}
return 0;
}