1. 程式人生 > >poj 2059 單調棧

poj 2059 單調棧

1.0 sca eas down rec cpp 操作 string typedef

  • 題意:求柱狀圖中最大矩形面積。

  • 單調棧:顧名思義就是棧內元素單調遞增的棧。

    每次插入數據來維護這個棧,假設當前須要插入的數據小於棧頂的元素,那就一直彈出棧頂的元素。直到滿足當前須要插入的元素大於棧頂元素為止。能夠easy求出某個數左邊或右邊,第一個大於或小於它的數,且復雜度是O(n)

  • 思路:easy先想到一個好的枚舉方式:以當前柱狀為擴展點,往左邊和右邊擴展。當遇到一個比當前柱狀小的柱狀時停止擴展。以當前柱狀的高度為矩形的高。向左右擴展的距離之差為矩形的長度,這樣對n個柱狀進行掃描之後可得最大矩形,復雜度是O(n2),顯然超時。

    本題用單調棧來做,維護一個條形圖高度的單調棧。

  • 心得:一定要想好了思路,並用偽代碼在草稿紙上寫一遍再動手寫,這道題單調棧實現部分花了大量時間debug,源於思路不清晰。

簡潔的實現:

  • 1.讀入當前柱狀的高度h。若h大於棧頂元素,則向棧中push(h, i) (i為當前柱狀的編號)。若h小於棧頂元素,則彈出棧頂元素,並得到(i?topi)?toph為棧頂柱狀所能擴展得到的最大矩形面積,以此面積來更新全局的最大面積。

    反復上操作,指導棧頂元素小於當前元素。


    2.最後得到一個單調遞增的棧,再來用(n?topi)?toph來表示棧頂元素所能組成的最大面積。處理並更新完整個棧就可以。

    註:我的代碼實現,沒實用事實上點做標記,而是一直條形圖合並的方法,代碼實現復雜了一些

    我的代碼:

#include <set>
#include <map>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; typedef long long int LL; const int M = 100009,INF = 0x3fffffff; int main(void) { //problem: poj2559, address:http://poj.org/problem?

id=2559 LL n, ans = -1, temp; while (scanf("%lld",&n), n) { ans = -1; pair<LL, LL> key(-99999999 , 1); stack<pair<LL, LL> > s; s.push(key); for (int i = 1; i <= n; i++) { key.second = 1; scanf("%lld", &key.first); int k = 0 ; while (s.top().first >= key.first) { temp = LL(s.top().second + k)*LL( s.top().first); if (temp > ans) ans = temp; key.second += s.top().second; k += s.top().second; s.pop(); } s.push(key); } for (int i = 0; !s.empty();) { temp = LL(s.top().first) * LL(i + s.top().second); if(temp > ans) ans = temp; i += s.top().second; s.pop(); } printf("%lld\n", ans); } return 0; }

poj 2059 單調棧