zoukankan      html  css  js  c++  java
  • 「单调栈,单调队列」总结

    整天做DP太累了……下午重新看了下有关单调栈的内容

    单调栈用途就在于求一个数列中,某点左侧第一个比他大(或小)的元素位置

    假设维护一个单调上升的栈。如果入栈元素小于栈顶那么就要开始pop。而pop掉的元素一定全都大于这个入栈元素。单调栈内的两个相邻元素a,b如果在原序列中不是相邻的,则意味着b的出现pop掉了中间的元素,因此这中间的元素必定都大于b。

    可以把单调栈的一个元素看做原序列的一块元素。b就代表了原序列中(a,b]

    一个元素的进入弹掉了一部分元素,由此求出最左延伸量。如果一个元素即将被pop,意味着终于出现了一个比它小的,就可以求出最右延伸量了。

    一个元素仅能进一次出一次,复杂度$O(n)$。

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define int long long
    using namespace std;
    inline int read(){
        int x(0),w(1); char c = getchar();
        while(c^'-' && (c<'0'||c>'9')) c = getchar();
        if(c == '-') w = -1, c = getchar();
        while(c>='0' && c<='9') x = (x<<3) + (x<<1) + c - '0', c = getchar();
        return x*w;
    }
    int n,a[100010],s[100010],top,l[100010],r[100010],sum[100010],L,R,ans=-0x3f3f3f3f;
    signed main(){
    //    freopen(".in","r",stdin);
        n = read();
        for(int i = 1; i <= n; ++i){
            a[i] = read();
            sum[i] = sum[i-1] + a[i];
        } 
        for(int i = 1; i <= n; ++i){
            while(a[s[top]] > a[i] && top > 0){
                r[s[top]] = i-1;
                --top;
            } 
            l[i] = s[top]+1;
            s[++top] = i;
        }
        while(top){
            r[s[top]] = n;
            --top;
        }
        for(int i = 1; i <= n; ++i){
            if(ans < (sum[r[i]]-sum[l[i]-1])*a[i]){
                ans = (sum[r[i]]-sum[l[i]-1])*a[i];
                L = l[i], R = r[i];
            }
        }
        printf("%lld
    %lld %lld",ans,L,R);
        return 0;
    } 
  • 相关阅读:
    java项目和web项目路径的区别
    ModelAndView跳转
    struts漏包和tomcat上传问题
    映射文件的路径写错的出现的错误
    hibernate二级缓存
    find命令小结
    【转】Python的XML-RPC简介
    Python的类实例方法,类方法,类静态方法
    itertools模块速查
    Python中处理时间 —— time模块
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/10825713.html
Copyright © 2011-2022 走看看