8
9 5 7 4 1 2 3 5
1 8
样例 找1-8的最值
思想:
用dp的方法,把f[i][j]的意思表示为从i到i+2^j区间内的最值,[i,i+2^j)
显然f[i][0]=a[i]。
所以DP可以推出所有
for(j=1;1<<j<=n;j++)
for(i=1;i+(1<<j)-1<=n;i++){
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
然后查找
是找一个最大的k,其满足2^k<=r-l+1,这样可以使得l+2^k与r-(2^k)覆盖整个l~r区域,即便覆盖了也没事
while(pow(2,k+1)<=r-l+1)k++; (想想为什么要k+1)
则所要找的最值就是 max(f[r][k],[l-(1<<k)+1][k])
模版
#include <iostream>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
int f[2000][2000];
int g[2000][2000];
int a[2000];
void RMQ(int n){ //传入参数为数组长度
int i,j;
for(i=1;i<=n;i++)
g[i][0]=f[i][0]=a[i];
for(j=1;1<<j<=n;j++)
for(i=1;i+(1<<j)-1<=n;i++){
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
g[i][j]=min(g[i][j-1],g[i+(1<<(j-1))][j-1]);
}
}
int find1(int l,int r){ //传入参数为l到r
int k=0;
while(pow(2,k+1)<=r-l+1)k++;
return max(f[l][k],f[r-(1<<k)+1][k]);
}
int find2(int l,int r){ //传入参数为l到r
int k=0;
while(pow(2,k+1)<=r-l+1)k++;
return min(g[l][k],g[r-(1<<k)+1][k]);
}
int main(){
freopen("in.txt","r",stdin);
int i,j,k,f1,f2,f3,f4,t4,t1,t2,t3,n,m;
int T,r,c,l;
cin >> n;
for(i=1;i<=n;i++)
cin >>a[i];
RMQ(n);
cin >> l >> r ;
cout << find1(l,r) << endl;
cout << find2(l,r) << endl;
return 0;
}