棧_單調棧_POJ2559_Largest Rectangle in a Histogram
阿新 • • 發佈:2018-12-19
思路分析:
本題是單調棧的典型應用, 下面先給出AC程式碼然後證明程式的正確性和分析其時間複雜度.
//POJ2559_Largest Rectangle in a Histogram #include <iostream> #include <cstdio> #include <algorithm> #include <vector> using namespace std; const int MAXN = 1e5 + 5; int re[MAXN], n; int main(){ while(scanf("%d", &n), n){ for(int i = 1; i <= n; ++i) scanf("%d", &re[i]); re[n + 1] = 0; vector<pair<int, int> > ve;//first:高度, second;寬度 long long res = 0; ve.push_back(make_pair(re[1], 1)); for(int i = 2; i <= n + 1; ++i){ int width = 0; while(!ve.empty() && ve.back().first >= re[i]) width += ve.back().second , res = max(res, (long long)ve.back().first * width), ve.pop_back(); ve.push_back(make_pair(re[i], width + 1)); } cout << res << endl; } return 0; }
對於上述程式的正確性證明:
設當前考察的是最左邊的第i個矩形, 那麼由原圖形中前i個矩形構成的區域的最大矩形子段的面積為 max{ 棧ve中儲存的矩形構成的區域的矩形子段面積最大值, res }, 且棧ve中儲存的矩形從棧底到棧頂(對應從左到右)矩形高度嚴格單調遞增(如下圖的CA和MN之間所有矩形), 因此棧中矩形構成的區域的最大矩形子段的最左邊的的高必定為ve中某個矩形左邊的高(如CA或EF), 且其右邊的高為ve中最後一個矩形右邊(邊MN)的一部分, 可以證明在每次第15行迴圈頭檢測之前該結論均成立, 因此結論正確
時間複雜度分析:
由於每次執行第17至19行的迴圈體均從ve中彈出1個元素(矩形), 對於ve, 僅在第14行和第18行的語句向其加入元素, 因此有n + 1個元素加入ve, 故第17至19行的迴圈體執行次數為O(n)次, 因此上述程式的時間複雜度為O(n)