1. 程式人生 > 實用技巧 >Largest Rectangle in a Histogram POJ - 2559 (單調棧)

Largest Rectangle in a Histogram POJ - 2559 (單調棧)

Description

A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rectangles have equal widths but may have different heights. For example, the figure on the left shows the histogram that consists of rectangles with the heights 2, 1, 4, 5, 1, 3, 3, measured in units where 1 is the width of the rectangles:

Usually, histograms are used to represent discrete distributions, e.g., the frequencies of characters in texts. Note that the order of the rectangles, i.e., their heights, is important. Calculate the area of the largest rectangle in a histogram that is aligned at the common base line, too. The figure on the right shows the largest aligned rectangle for the depicted histogram.

Input

The input contains several test cases. Each test case describes a histogram and starts with an integer n, denoting the number of rectangles it is composed of. You may assume that 1<=n<=100000. Then follow n integers h1,...,hn, where 0<=hi<=1000000000. These numbers denote the heights of the rectangles of the histogram in left-to-right order. The width of each rectangle is 1

. A zero follows the input for the last test case.

Output

For each test case output on a single line the area of the largest rectangle in the specified histogram. Remember that this rectangle must be aligned at the common base line.

Sample Input

7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0

Sample Output

8
4000

Hint

Huge input, scanf is recommended.

題意:n個矩形,然後給出每個矩形的高(寬度都為1),求出其中最大矩形的面積

思路:對於高度遞增的矩形序列,我們可以嘗試以每一塊的高度為最終高度,然後向後延申寬度,最大面積就是答案。

但是當前高度小於之前矩形的高度時,我們可以先回溯,之前的矩形肯定時高度遞增的,回溯的目的時更新之前矩形所能形成的最大的答案

(黃色區域為回溯時,矩形高度仍大於當前矩形,更新的答案)

直到之前的矩形高度小於當前矩形,就將之前所積累的(寬度+1),當成新矩形的寬度,高度就是當前矩形高度,這樣的對於後面的矩形,又形成了新的遞增型矩形序列

而且由於回溯的時候,我們將捨棄的部分能形成的最大面積已經考慮了,所以不會出現答案遺失(對於後面的矩形紫色無法利用的,被當前矩形限制了高度,所以捨棄,加入擴充套件了的當前矩形)

最後,對整個遞增的矩形序列進行一次回溯,答案的更新,為了方便將其最後加入一個高度為0的矩形,當然不加另外判斷也ok

(用不用棧無所謂,重要的是單調性)

#include<bits/stdc++.h>
using namespace std;
int h[100005], w[100005];
stack<int> s;
int main(){
    int n;
    while (~scanf("%d", &n) && n){
        while (!s.empty()) s.pop();
        for (int i = 0; i < n; i++)
            scanf("%d", &h[i]);
        h[n] = -1;
        long long ans = 0;
        for (int i = 0; i <= n; i++){
            if (s.empty() || h[i] > s.top()){
                s.push(h[i]);
                w[s.size()] = 1;
            }
            else {
                int width = 0;
                while (!s.empty() && h[i] <= s.top()){
                    width += w[s.size()];
                    ans = max(ans, (long long)width * s.top());
                    s.pop();
                }
                s.push(h[i]); w[s.size()] = width + 1;
            }
        }
        printf("%lld\n", ans);
    }
}