• 单调栈以及应用


    单调栈有以下两个性质:

    1、若是单调递增栈,则从栈顶到栈底的元素是严格递增的。若是单调递减栈,则从栈顶到栈底的元素是严格递减的。

    2、越靠近栈顶的元素越后进栈。

    单调栈与单调队列不同的地方在于栈只能在栈顶操作,因此一般在应用单调栈的地方不限定它的大小,否则会造成元素无法进栈。

    元素进栈过程:对于单调递增栈,若当前进栈元素为e,从栈顶开始遍历元素,把小于e或者等于e的元素弹出栈,直接遇到一个大于e的元素或者栈为空为止,然后再把e压入栈中。对于单调递减栈,则每次弹出的是大于e或者等于e的元素。

    单调栈解决的是以某个值为最小(最大)值的最大区间。

    实现方法是:求最小值(最大值)的最大区间,维护一个递增(递减)的栈;当遇到一个比栈顶小的值的时候开始弹栈,弹栈停止的位置到这个值的区间即为此值左边的最大区间;同时,当一个值被弹掉的时候也就意味着比它更小(更大)的值来了,也可以计算被弹掉的值得右边的最大区间。

    具体方法就是:因为求小值的大区间,采用栈底向栈顶递增的方式维护单调栈。

    起始时,元素的左右区间均为自身位置。

    当遇到栈顶元素大于当前将要入栈的数值时候,将栈顶元素的左区间赋值给入栈元素的左区间,同时将入栈元素当前位置赋值给栈顶元素的右区间,之后栈顶元素出栈,继续判断入栈元素跟栈顶元素的大小。(总的来说就是谁让你出栈,谁就是你的右区间,你让谁出栈,谁的左区间就是你的左区间)

    当全部元素入栈成功后,最后在单调栈中的元素为由小到大排列,只需要将最后入栈的栈顶元素位置保存下来,将该位置赋值给栈内剩余元素的右区间即可

    struct Node
    {
        int value;
        int left;
        int right;
    };
    int main()
    {
         int n,j;
        cin >> n;
        int maxarea=0;
        vector<Node> h(n+1);
        stack<int> monotone;
        for (int i = 1; i <= n; i++)
        {
            cin >> h[i].value;
            h[i].left=h[i].right=i;
        }
        for(int i=1;i<=n;i++)  
        {  
            while(!monotone.empty() && h[monotone.top()].value > h[i].value)  
            {  
                h[monotone.top()].right=i-1;  
                h[i].left=h[monotone.top()].left;  
                monotone.pop();  
            }  
            monotone.push(i);  
        }  
        if(!monotone.empty())  
            j=monotone.top();  
        while(!monotone.empty())  
        {  
            h[monotone.top()].right=j;  
            monotone.pop();  
        }  
        for(int i=1;i<=n;i++)  
        {  
            int area = h[i].value*(h[i].right-h[i].left+1);
            maxarea=maxarea<area ? area : maxarea;
            //cout<<h[i].value<<":"<<h[h[i].left].value<<" "<<h[h[i].right].value<<endl;  
        }
        cout<< maxarea<<endl;
        return 0;  
    }

    这段程序维护了一个单调栈,来得到每个元素的左右边界。可以用来求最大矩形的面积,后面的一点程序就是计算一串数字在直方图中构成的最大矩形面积。

  • 相关阅读:
    ZOJ 2702 Unrhymable Rhymes(DP)
    unique() 去重函数
    HDU 4712 Hamming Distance(随机算法)
    HDU 4708 Rotation Lock Puzzle(模拟)
    HBase源代码分析之MemStore的flush发起时机、推断条件等详情(二)
    Androidproject师进阶之路 :《Android开发进阶:从小工到专家》上市啦!
    POJ1062 昂贵的聘礼(最短路)
    easyui required 提交验证
    leetcode
    【翻译自mos文章】在Oracle单机数据库中定义database service
  • 原文地址:https://www.cnblogs.com/mini-coconut/p/9108232.html
Copyright © 2020-2023  润新知