• poj 2452(RMQ+二分查找)


    题目链接:

    http://poj.org/problem?id=2452

    题意:在区间[1,n]上找到满足 a[i]<a[k]<a[j] (i<=k<=j) 的最大子区间 (j-i)如不存在输出 -1.

    思路:枚举i,找到 i右边第一个不大于(不是小于) a[i]的数a[k](二分查找+RMQ某段区间的最小值是否小于a[i].最后确定到一个点),于是
    我们可以得到在区间[i,k-1]范围内的数都会大于 a[i] ,所以对于下标i,它对应的最长区间必定在[i,k-1]之间。

    所以,我们只要找到这个区间最大值 a[j] (这里又要用到RMQ查找区间最大值下标) 所以我们可以得到相对于点 i,其对应的最长子区间是[i,j]

    例: 2 3 4 5 3 2 6 7

    我们先枚举下标1 ,算出 右边不大于它的点是 a[6] = 2

    然后对于 区间 2 3 4 5 3 2 最大值是 a[4] = 5 ,所以相对于下标1最长的区间是 1 - 4,依此类推。

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<math.h>
    #include<algorithm>
    using namespace std;
    const int N = 50005;
    ///储存区间最大最小值的下标
    int max_dp[2*N][30];
    int min_dp[2*N][30];
    int a[N];
    int MAX(int i,int j){
        if(a[i]>a[j]) return i;
        return j;
    }
    int MIN(int i,int j){
        if(a[i]>a[j]) return j;
        return i;
    }
    void init_RMQ(int n){
        for(int i=1;i<=n;i++){
            max_dp[i][0] = min_dp[i][0]=i;
        }
        for(int j=1;(1<<j)<=n;j++){
            for(int i=1;i+(1<<j)-1<=n;i++){
              max_dp[i][j] = MAX(max_dp[i][j-1],max_dp[i+(1<<(j-1))][j-1]);
              min_dp[i][j] = MIN(min_dp[i][j-1],min_dp[i+(1<<(j-1))][j-1]);
            }
        }
    }
    int MAX_RMQ(int l,int r){
        int k  = (int)(log(r-l+1.0)/log(2.0));
        return MAX(max_dp[l][k],max_dp[r-(1<<k)+1][k]);
    }
    int MIN_RMQ(int l,int r){
        int k = (int)(log(r-l+1.0)/log(2.0));
        return MIN(min_dp[l][k],min_dp[r-(1<<k)+1][k]);
    }
    int binary(int value,int l,int r){
        while(l<=r){
            if(l==r) return l;
            int mid = (l+r)>>1;
            //printf("MIN_RMQ:%d
    ",a[MIN_RMQ(l,mid)]);
            if(value<a[MIN_RMQ(l,mid)]){
                l = mid+1;
            }else r = mid;
        }
    }
    int main()
    {
        int n;
        while(scanf("%d",&n)!=EOF){
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
            }
            init_RMQ(n);
            int ans = 0;
            for(int i=1;i<=n;i++){
                int value = a[i];
                int k = binary(value,i+1,n);
    
                int j = MAX_RMQ(i,k);
                //printf("%d %d %d
    ",i,k,j);
                if(a[j]>a[i])
                ans = ans>j-i?ans:j-i;
            }
            if(ans==0) printf("-1
    ");
            else printf("%d
    ",ans);
        }
    
    }
  • 相关阅读:
    一个秒杀系统的设计
    2018年终总结-从我所在的团队回首一年技术变迁
    温习LOGO语言
    微信公众平台配置-笔记
    Spring mongotemplate使用
    三种方法实现MNIST 手写数字识别
    Python 实现0-1背包
    Python 实现快速排序和随机快速排序
    Spring+SpringMVC+Mybatis搭建的网站的处理流程总结
    Mybatis功能架构及执行流程
  • 原文地址:https://www.cnblogs.com/liyinggang/p/5350540.html
Copyright © 2020-2023  润新知