poj2452 Sticks Problem RMQ问题

Deadly 提交于 2020-02-12 11:06:24

题目大意说:给出一系列的木棒的长度,求出一个最大的区间[x,y],满足所有的len[k]>len[i] && len[k]<len[j] ,i<=k<=j。我看的题目分类说这个题目用RMQ,所有就用了RMQ实现,由于开始的时候我是枚举的所有的区间,所以肯定超时,后来改为从i找出以i开始的最大区间范围,然后在这个范围内求出最大值的下标j,那么j就是从i开始的所有>i且<j的最大区间,枚举采用二分,这样时间复杂度为O(nlogn).

#include <iostream>#include <stdio.h>#include <cmath>const int N=50001;using namespace std;int m[N],large[N][17],smal[N][17];inline int get_max(int a,int b){    return a>b?a:b;}inline int get_min(int a,int b){    return a<b?a:b;}void initrmq(int n){    int i,j;    for(i=0;i<n;i++)    {        large[i][0]=i;        smal[i][0]=i;    }    for(j=1;(1<<j)<=n;j++)    {        for(i=0;i+(1<<j)-1 < n;i++)        {            if(m[large[i][j-1]] > m[large[i+(1<<(j-1))][j-1]])                large[i][j]=large[i][j-1];            else                large[i][j]=large[i+(1<<(j-1))][j-1];            if(m[smal[i][j-1]] < m[smal[i+(1<<(j-1))][j-1]])                smal[i][j]=smal[i][j-1];            else                smal[i][j]=smal[i+(1<<(j-1))][j-1];        }    }}int querymin(int i,int j){    int k=(int)(log(1.0*(j-i+1))/log(2.0));    if(m[smal[i][k]] < m[smal[j-(1<<k)+1][k]])        return smal[i][k];    return smal[j-(1<<k)+1][k];}int querymax(int i,int j){    if(i>j)    {        int tmp=i;        i=j;        j=tmp;    }    int k=(int)(log(1.0*(j-i+1))/log(2.0));    if(m[large[i][k]] > m[large[j-(1<<k)+1][k]])        return large[i][k];    return large[j-(1<<k)+1][k];}//找出以i开头的最大区间范围int findIdx(int n,int l){    int mid,i=l,j=n-1;    while(i+1<=j)    {        mid=(i+j)>>1;        if(querymin(l,mid) == l)//如果现在的区间最小值下标是l,则扩大范围,否则缩小范围            i=mid+1;        else            j=mid-1;    }    return j;}int solve(int n){    int i,j,ans=0,k,l,r;    l=0;    r=n-1;    for(i=0;i<n-1;i++)    {        j=findIdx(n,i);        k=querymax(i,j);//        cout<<j<<" "<<k<<endl;        if(k-i > ans)            ans=k-i;    }    if(ans)        return ans;    return -1;}int main(){    int i,n;    while(scanf("%d",&n)!=EOF)    {        for(i=0;i<n;i++)            scanf("%d",&m[i]);        memset(large,0,sizeof(large));        memset(smal,0,sizeof(smal));        initrmq(n);        int ans=solve(n);        printf("%d\n",ans);    }    return 0;}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!