RMQ<区间最值查找,O(n*logn)

来源:互联网 发布:上海近几年gdp数据 编辑:程序博客网 时间:2024/05/29 04:36

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;}


0 0