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;
    }
    
  • 相关阅读:
    【开发笔记】- Linux命令大全
    【面试突击】- SpringMVC那些事(一)
    【阿里云开发】- 搭建和卸载svn服务器
    【阿里云开发】- 安装tomcat
    SpringCloud之Eureka服务发现和注册(二)
    springcloud之环境工程模块(一)
    java多线程中篇(三) —— 线程的控制(创建,运行,阻塞,中断,结束)
    java多线程中篇(二) —— 线程的创建和Synchronized锁关键字
    java多线程中篇(一) —— Thread详情
    JUC之AbstractQueuedSynchronizer原理分析
  • 原文地址:https://www.cnblogs.com/zsyacm666666/p/6812896.html
Copyright © 2011-2022 走看看