Largest Rectangle in a Histogram

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)

Problem 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

思路:

单调栈的一题,有题目中的题目可以看出,想要找出最大的矩形,那么假如左边或者右边都大于等于a[i]的话,那么这个矩形肯定就可以延伸到左边或者右边,直到到了第一个小于a[i]的值才停止,这样矩形的面积就是(右边 - 左边) * a[i]想要找到左边第一个小于a[i]的值就可以用单调栈实现了。需要注意的是需要开最后数据过大,需要开到longlong。

#include <iostream>
#include <cstdio>
#include <stack>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 100010;
int main() {
    int n;
    int a[maxn];
    while (scanf("%d", &n) != EOF && n) {
        stack<int> s;
        int l[maxn] = {0}, r[maxn] = {0};
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
        for (int i = 1; i <= n; i++) {
            while (!s.empty() && a[s.top()] >= a[i]) s.pop();
            if (s.empty()) l[i] = 1;
            else l[i] = s.top() + 1;
            s.push(i);
        }
        while (!s.empty()) s.pop();
        for (int i = n; i > 0; i--) {
            while (!s.empty() && a[s.top()] >= a[i]) s.pop();
            if (s.empty()) r[i] = n;
            else r[i] = s.top() - 1;
            s.push(i);
        }
        ll Max = 0;
        for (int i = 1; i <= n; i++) {
            ll ans = a[i] * (ll)(r[i] - l[i] + 1);
            Max = max(ans, Max);
        }
        printf("%lld\n", Max);
    }
    return 0;
}