解题报告 之 POJ 2559 Largest Rectangle in a Histogram

来源:互联网 发布:超浓密睫毛膏 知乎 编辑:程序博客网 时间:2024/04/29 03:19

解题报告 之 POJ 2559 Largest Rectangle in a Histogram


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 34 1000 1000 1000 10000

Sample Output

84000

Hint

Huge input, scanf is recommended.

题目大意:给你一堆宽度为1,高度不同的矩形条。问你能框出一个最大矩形面积为多少。

分析:有两种办法解题,比较直观的是DP,还有一种方法叫作单调栈。我两种方法都试了一下。首先先说一下DP的方法。对于每一个矩形。我们确定一下其左右两边高度>=它的矩形数量,如果遇到<的,则停止扩展,因为一定会在更新那个遇到的最小矩形的时候把当前这种情况考虑进去,所以现在就不用扩展了。

如果有h[i]表示高度,l[i]表示i左边有几个矩形比i高,r[i]表示i右边有几个比i高。最后扫一遍求一个最大面积即可。有一个技巧就是再扩展左右的时候可以dp利用已有的结果。

上代码:
#include<iostream>#include<cstdio>#include<algorithm>using namespace std;typedef long long ll;const int MAXN = 1e5 + 10;const int INF = 0x3f3f3f3f;ll h[MAXN];ll l[MAXN], r[MAXN];int main(){int n;while(scanf( "%d", &n ) == 1 && n){h[0] = h[n + 1] = -INF;for(int i = 1; i <= n; i++){scanf( "%lld", &h[i] );}for(int i = 1; i <= n; i++){l[i] = r[i] = i;}for(int i = 1; i <= n; i++){while(h[l[i] - 1] >= h[i])l[i] = l[l[i] - 1];}for(int i = n; i >= 1; i--){while(h[r[i] + 1] >= h[i])r[i] = r[r[i] + 1];}ll ans = 0;for(int i = 1; i <= n; i++){ans = max( ans, (r[i] - l[i] + 1)*h[i] );}printf( "%lld\n", ans );}}

-----------------------------------------------------------------------------------------------------------------------------------------------------

下面来看看第二种方法:单调栈。单调栈主要思想是维护每个元素能向左扩展最多多少?一个元素进入栈之前总要先处理一下栈顶的元素(看看是不是可以扩展到当前元素),处理完后入栈,一旦入栈则说明这个元素的左扩展已确定;同理,被扩展的栈顶元素出栈表示右扩展确定。

那么我们每读入一个新矩形高度,我们先确定此时左扩展最大长度,顺势再更新一下以当前矩形为最低矩形时的面积。注意最后要加入0来强制统计加入了所有矩形的情况。

上代码:
#include <stdio.h>#define max(a,b) a > b ? a : b#define N 100005int q[N]={-1},w[N];     //w记录的是从这个点开始,之前有几个高度大于等于此高度.int main(){    int n,h;    while(scanf("%d",&n),n)    {        int top = 0;        __int64 ans = 0;        for(int i=1;i<=n+1;i++)        {            if(i != n+1)                scanf("%d",&h);            else                h = 0;            if(h > q[top])                q[++top] = h , w[top] = 1;            else            {                __int64 cnt = 0;                while(h <= q[top])                {                    ans = max(ans ,(cnt+w[top])*q[top] );                    cnt += w[top--];                }                q[++top] = h;                w[top] = cnt+1;            }        }        printf("%I64d\n",ans);    }    return 0;}



嘉神出的周赛真不是盖得。积极备战大连。

0 0
原创粉丝点击