zoukankan      html  css  js  c++  java
  • poj 2559(单调栈)

    poj 2559(单调栈)

    对于此题,我们需要找到每个点分别向左右能够扩展到的连续长度,能够扩展的条件为:这些区间的元素值都都大于等于当前点的值。
    使用单调栈维护从起点到当前点的递增序列,如果栈顶元素大于当前点,我们就一直将栈中元素弹出,直到遇到小于当前点的元素,以此来维护栈的递增性,显然此时的点最远可以扩展到当前栈元素的位置-1,即我们找到了当前点的扩展边界。我们需要证明的是:前面弹出的元素对之后的点没有影响,即i之前大于h[i]的元素必然不是h[i+1]可以扩展到的边界。我们可以分情况讨论

    1. 若h[i+1]>h[i] 那么 h[i+1]显然无法再向左扩展,边界是h[i],证明是对的
    2. 若h[i+1]<=h[i] 那么 之前({j<i , h[j]>h[i]})显然都是满足扩展条件的,那么这些点都不能成为边界,即因为h[i]而弹出的元素对h[i+1]是没有影响的。证明是对的
      这样的证明是具有递推性的,我们可以用数学归纳法证明其正确性。

    由此我们可以线性求得每个元素向左扩展的边界,向右扩展的边界只需倒着做一遍相同的操作即可,总复杂度是O(n)。

    #include <queue>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #define ll long long
    #define inf 1000000000LL
    #define mod 1000000007
    using namespace std;
    int read()
    {
        int x=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            x=x*10+ch-'0';
            ch=getchar();
        }
        return x*f;
    }
    const int N=1e5+10;
    int L[N],R[N],st[N],h[N];
    int main(){
         while(true){
            int n=read();
            if(n==0) break;
            for(int i=0;i<n;i++) h[i]=read();
            int t=0;
            for(int i=0;i<n;i++){
                 while(t>0&&h[st[t-1]]>=h[i]) t--;
                 L[i]=t==0?-1:st[t-1];
                 st[t++]=i;
            }
    
            t=0;
            for(int i=n-1;i>=0;i--){
                 while(t>0&&h[st[t-1]]>=h[i]) t--;
                 R[i]=t==0?n:st[t-1];
                 st[t++]=i;
            }
    
            ll ans=0;
            for(int i=0;i<n;i++){
                ans=max(ans,(ll)h[i]*(R[i]-L[i]-1));
            }
            printf("%lld
    ",ans);
         }
         return 0;
    }
    
  • 相关阅读:
    021.day21 反射 Class类 反射常用操作
    020.day20 线程概述 多线程优缺点 线程的创建 线程常用方法 生命周期 多线程同步
    019.day19 缓冲流 对象流 标准输入输出流
    018.day18 map集合如何实现排序 File类 IO流 字节流 字符流 编码
    017.day17 Map接口 克隆 treeSet集合排重缺陷
    016.day16 HashSet TreeSet 比较器Comparable Comparator
    015.day15
    014.day14
    013.day13
    线程
  • 原文地址:https://www.cnblogs.com/zsyacm666666/p/6812896.html
Copyright © 2011-2022 走看看