POJ 2559 Largest Rectangle in a Histogram 单调栈

Largest Rectangle in a Histogram
Time Limit:1000MS    Memory Limit:65536KB    64bit IO Format:%lld & %llu

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.

解题思路:
这题刚拿到的时候感觉是一个贪心的题目,但是后来分析感觉又像动态规划,再分析感觉不好下手
最后别人告知是单调栈的问题

这题的策略是寻找某一高度作为最终高度的左右扩展范围
对于i这个范围是L[i]和R[i]
L[i]是从i往左找,找到的第一个比i高度小的位置+1
R[i]是从i往右找,找到的第一个比i高度小的位置-1
最后循环遍历一下,找到最大的  i的高度*(R[i]-L[i]+1)就是结果
这个方法是能解决问题的,但是暴力的做的话复杂度比较的高
那么怎么办
单调栈是一个实现的话就是一个普通的栈,只不过我们为了满足单调栈的性质添加了一些操作
栈是后进先出的,单调性指的是严格的递增或者递减。
单调栈有一个重要的性质:
1、若是单调递增栈,则从栈顶到栈底的元素是严格递增的。若是单调递减栈,则从栈顶到栈底的元素是严格递减的。
这个栈是通过人工的添加策略来实现的,并不是STL有这么一个栈,只是我们维护一个栈,他符合上述性质

首先从左往右找(使用递减栈)
那么对于这题,每次添加一个高度的时候,我们看栈顶的元素是不是比它大了,大了就pop,知道栈顶的元素是比它小的。
然后把这个点的高度放进去,这个高度的L[i]就是栈里的那个高度所在的位置+1了。

画个例子
直方图2145133
L[i]1134166
R[i]1744777
注意直方图最左边的和最右边都增加一个高度无穷小的高度,用来区别
如果你用单调栈推出了上述数据,ok,你就懂了

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
const int maxn = 100005 ;
int n ;
struct node{
    int val;
    int pos ;
};
stack<node> qq ;
int arry[maxn] ;
int l[maxn];
int r[maxn];
int main(){
    while(~scanf("%d",&n),n){
        for(int i=1;i<=n;i++){
            scanf("%d",&arry[i]);
        }
        node def ;
        def.val = -1 ;
        def.pos = 0 ;
        while(!qq.empty())qq.pop();
        qq.push(def);
        for(int i=1;i<=n;i++){
            while(qq.top().val>=arry[i])qq.pop();
            node t ;
            t.val = arry[i] ;
            l[i] = qq.top().pos+1 ;
            t.pos = i ;
            qq.push(t);
        }
        while(!qq.empty())qq.pop();
        def.pos = n+1 ;
        qq.push(def);
        for(int i = n;i>=1;i--){
            while(qq.top().val>=arry[i])qq.pop();
            node t ;
            t.val = arry[i] ;
            r[i] = qq.top().pos-1 ;
            t.pos = i ;
            qq.push(t);
        }
        long long ans = 0 ;
        for(int i=1;i<=n;i++){
            long long temp = (long long)arry[i] ;
            ans = max(ans,temp*(r[i]-l[i]+1)) ;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值