RMQ问题 裸题

来源:互联网 发布:国家要打仗了知乎 编辑:程序博客网 时间:2024/06/05 15:20
RMQ算法,是一个快速求区间最值的离线算法,预处理时间复杂度O(n*log(n)),查询O(1),所以是一个很快速的算法,当然这个问题用线段树同样能够解决。

问题:给出n个数ai,让你快速查询某个区间的的最值。

算法分类:DP+位运算

#include<iostream>#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#include<algorithm>using namespace std;const int MAX=100000;int mx[MAX][20],mn[MAX][20];int a[MAX];//设A[i]是要求区间最值的数列,F[i, j]表示从第i个数起连续2^j个数中的最大值(DP的状态)//F[i,0]就等于A[i](DP的初始值)/*把F[i,j]平均分成两段(因为f[i,j]一定是偶数个数字)从i到 i+2^(j-1)-1 为一段, i+2^(j-1) 到 i+2^j-1 为一段     长度都为2^(j-1)F[i,j]就是这两段各自最大值中的最大值状态转移方程F[i, j]=max(F[i,j-1],F[i+2^(j-1),j-1])*/int n;void init(){for(int i=1;i<=n;i++)mx[i][0]=mn[i][0]=a[i];// int m=(floor||int)(log((double)n)/log(2.0)); for(int j=1;(1<<j)<=n;j++)         // for(j=1;j<=m;j++) for(int i=1;i+(1<<j)-1<=n;i++){        // for(i=1;i<=n;i++) // if(i+(1<<(j-1))<=n) mx[i][j]=max(mx[i][j-1],mx[i+(1<<(j-1))][j-1]);// if(i+(1<<(j-1))<=n) mn[i][j]=min(mn[i][j-1],mn[i+(1<<(j-1))][j-1]);}}int query(int l,int r){int m=(int)(log((double)(r-l+1))/log(2.0));int a=max(mx[l][m],mx[r-(1<<m)+1][m]);int b=min(mn[l][m],mn[r-(1<<m)+1][m]);return a-b;// return a;// return b;}int main(){int m;int L,R;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&a[i]);init();for(int i=1;i<=m;i++){scanf("%d%d",&L,&R);printf("%d\n",query(L,R));}return 0;}

1 0
原创粉丝点击