單調棧理解及應用

CN_swords發表於2017-11-12
單調棧:棧內元素,按照(單調遞增或單調遞減)排序,如果新入棧元素破壞了單調性,就彈出棧內元素,直到滿足單調性。
作用:o(n)時間複雜度分別求左右兩邊第一個比它大或比它小的元素。

(單調遞增棧為例)
維護:每次入棧前先檢驗棧頂元素和進棧元素的大小,判斷棧內元素是否出棧(棧內元素大於等於入棧元素則棧內元素出棧),直到進棧元素入棧。
發揮作用的原理:
1.進棧元素能入棧的時候,此時棧頂元素一定是第一個左邊第一個比進棧元素小的元素。
2.棧內元素出棧的時候,此時進棧元素一定是第一個右邊第一個比棧頂元素小的元素。

ok!
poj 2559
題解: 列舉每個位置高度,對於每個高度(h),找兩邊第一個比它小的位置(l,r),那麼以當前高度構柱形面積為:(r-l-1)*h

code:
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
typedef __int64 LL;

const int N = 100010;
struct Node{
    int L,R;
    int id,val;
}node[N];
stack<Node> sta;
int main()
{
    int n;
    while(~scanf("%d",&n) && n){
        while(sta.size()) sta.pop();
        for(int i = 1; i <= n; i++){
            node[i].L = 0, node[i].R = n+1;
            node[i].id = i;
            scanf("%d",&node[i].val);
            while(!sta.empty() && sta.top().val > node[i].val){
                node[sta.top().id].R = i;
                sta.pop();
            }
            if(!sta.empty())
                node[i].L = sta.top().id;
            sta.push(node[i]);
        }
        LL mx = 0;
        for(int i = 1; i <= n; i++)
        {
            LL tmp = (LL)(node[i].R-node[i].L-1)*(LL)node[i].val;
            mx = max(mx,tmp);
        }
        printf("%lld\n",mx);
    }
    return 0;
}


相關文章