• poj2452 Sticks Problem RMQ问题


    题目大意说:给出一系列的木棒的长度,求出一个最大的区间[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;
    }
  • 相关阅读:
    优秀的3D游戏开发系统和虚拟现实技术!
    C#反射实例(转)
    网易学院
    static 并发
    设计模式Strategy 策略模式
    1:统一建模语言UML轻松入门基本概念
    标准CSS 列表写法
    超级简单:ASP.NET Localization (本地化,多语言)
    js用escape()轻松搞定ajax post提交汉字的乱码问题
    认识.NET的集合
  • 原文地址:https://www.cnblogs.com/buptLizer/p/2179536.html
Copyright © 2020-2023  润新知