Largest Rectangle in a Histogram POJ2559(单调栈模板)

题目如下:
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.

题目分析:单调栈的模板题,关于单调栈,其实适用于求解最小值的最大区间以及最大值的最大区间。对于这一题而言要求直线上的最大矩形和,而且要是一段以一段上的最小高度来计算。很明显是一道最小值的最大区间的模型题。
做法:对于最小值的最大区间问题,首先用单调栈维护递增序列。如果发现一个当前值小于栈顶元素,就弹栈直到栈顶元素小于等于当前元素或者栈空。然后我们要累积的和就是我们弹出来的这些元素。用一个minval维护这些元素中的最小值并且用lsum维护这些元素的总宽度。用sum维护最终结果。但是要注意的是sum的维护是要在每次弹出一个元素的时候就进行。即:每弹出一个元素就要进行一次sum的更新。原因可能这一个弹出的元素远远大于其他的。可能这一个元素的高度就比其他所有的和都要大。
代码入下:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<stack>
using namespace std;
const int maxx = 100000 + 50;
int n, aa;
struct My {
    long long w, h;
    My() {}
    My(int a, int b): w(a), h(b) {}
} x;

stack<My>sta;
int cun[maxx];
int main() {
    while(scanf("%d", &n) != EOF) {
        if(n == 0)break;
        while(!sta.empty())sta.pop();
        x.w = x.h = 0;
        sta.push(x);
        long long sum = -1, lsum = 0, minval = 1LL << 34;
        for(int i = 0; i < n; i++) {
            scanf("%lld", &x.h); x.w = 1;
            if(x.h >= sta.top().h) {
                sta.push(x);
            } else {
                minval = 1LL << 34; lsum = 0;
                while(!sta.empty()) {
                    if(sta.top().h <= x.h)break;
                    lsum += sta.top().w;
                    minval = min(minval, sta.top().h);
                    sum = max(sum, lsum * minval);
                    sta.pop();
                }
                sta.push(My(lsum, minval));
                sta.push(x);
            }
        }
        lsum = 0; minval = 1LL << 34;
        while(!sta.empty()) {
            lsum += sta.top().w;
            minval = min(minval, sta.top().h);
            sum = max(sum, lsum * minval);
            sta.pop();
        }
        printf("%lld\n", sum);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值