• 《Largest Rectangle in a Histogram》


    非常好的一道单调栈的题。

    首先说一下单调栈,它维护的是一个单调的序列。

    如果维护递增序列,那么栈顶大于当前值时,就pop栈顶,这样之后可以发现,栈顶的元素是左边最近的小于当前值的元素。

    那么对于这道题,有一个很巧妙的转化方法:合并矩形

    图片详解可见:https://blog.csdn.net/qq_19829595/article/details/96019508

    考虑当前的栈中序列为

    1 2 3 4 5 6.

    那么合并矩形时:

    sum = 6*1.

    sum = 5*2

    sum = 4*3

    sum = 3*4

    sum = 2*5

    sum = 1*6

    最后合并为 h = 1,w = 6.

    可以发现,我们这样是在计算以栈顶位置结尾的能组成的最大矩形。

    避免一直递增最后没有比较的情况发生,我们让h[n+1] = 0,保证了最后肯定会计算。

    注意的是,如果ans = -INF,那么所以高度都为0的情况时,依旧不会算,这时可以让h[n+1] = -1。

    或者一开始ans = 0.

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef long double ld;
    typedef pair<LL,int> pii;
    const int N = 1e5+5;
    const int M = 1e6+5;
    const LL Mod = 1e9+7;
    #define rg register
    #define pi acos(-1)
    #define INF 1e9
    #define INM INT_MIN
    #define dbg(ax) cout << "now this num is " << ax << endl;
    inline LL read()
    {
        LL x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
    LL S[N],w[N],h[N];
    int main() 
    {
        int n;
        while(n = read(),n != 0)
        {
            for(int i = 1;i <= n;++i) h[i] = read();
            int top = 0;
            LL ans = 0;
            h[n+1] = 0;
            for(int i = 1;i <= n+1;++i)
            {
                if(h[i] > S[top])
                {
                    S[++top] = h[i];
                    w[top] = 1;
                }
                else
                {
                    LL width = 0;
                    while(top != 0 && S[top] > h[i])
                    {
                        width += w[top];
                        ans = max(ans,width*S[top]);
                        top--;
                    } 
                    S[++top] = h[i];
                    w[top] = width+1;
                }
            }
            printf("%lld\n",ans);
        }
        system("pause");
        return 0;
    }
    View Code
  • 相关阅读:
    CF 552(div 3) E Two Teams 线段树,模拟链表
    单词接龙
    书的复制 动规,贪心
    C++文本处理&造轮子
    【NOIP2015】【Luogu2661】信息传递(有向图最小环)
    平时上机练习的注意点(NOIP2018)
    【SHOI2009】【BZOJ2028】会场预约(线段树染色)
    【AHOI2009】【BZOJ1798】Seq 维护序列seq(线段树模板,易错提醒)
    2018 “百度之星”程序设计大赛
    2018 “百度之星”程序设计大赛
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/13418953.html
Copyright © 2020-2023  润新知