POJ 2559 Largest Rectangle in a Histogram 单调栈

来源:互联网 发布:开淘宝保证金怎么退 编辑:程序博客网 时间:2024/05/29 19:39
Largest Rectangle in a Histogram
Time Limit:1000MS    Memory Limit:65536KB    64bit IO Format:%lld & %llu
SubmitStatus

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 integern, denoting the number of rectangles it is composed of. You may assume that1<=n<=100000. Then follow n integers h1,...,hn, where0<=hi<=1000000000. These numbers denote the heights of the rectangles of the histogram in left-to-right order. The width of each rectangle is1. 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 34 1000 1000 1000 10000

Sample Output

84000

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了。

画个例子
直方图2145133L[i]1134166R[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;}





0 0
原创粉丝点击