POJ2559-Largest Rectangle in a Histogram

Largest Rectangle in a Histogram

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 22077   Accepted: 7137


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 follown integersh1,...,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 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 3
4 1000 1000 1000 1000
0

Sample Output

8
4000




解题心得:

1、其实这个题是动态规划加搜索,先说搜索部分,能够以某个柱形为中心形成公共矩形面积的,只有柱形左方和右方都高于它,所以将每一个柱形为中心向左向右搜索,但是这样毫无疑问会超时。所以需要在这个搜多的基础上优化。


2、然后就是动态规划部分,首先我们可以使用一个right[]组记录一下这个这个柱形最左方的大于它的那个柱形的位置,用left[]数组记录一下最右方的柱形大于它的那位置。当它的下个柱形在搜索的时候,如果比左方的那个柱形高度小就,这个柱形的左右边界就可以直接调到左方的哪个柱形的左右边界再开始找。然后得到答案就行了。


#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
typedef long long ll;
ll num[maxn];
ll Right[maxn],Left[maxn];
int main()
{
    ll n;
    while(scanf("%lld",&n) && n)
    {
        memset(Right,0,sizeof(Right));
        memset(Left,0,sizeof(Left));
        
        Left[1] = 1;
        Right[n] = n;
        for(ll i=1;i<=n;i++)
            scanf("%lld",&num[i]);
            
        //找左方的从左方开始才能够动态规划
        for(ll i=2;i<=n;i++)
        {
            ll now = i;
            while(now >= 1 && num[i] <= num[now-1])
                now = Left[now-1];
            Left[i] = now;
        }

        //找右方的就从右方开始
        for(ll i=n-1;i>=1;i--)
        {
            ll now = i;
            while(now <n && num[i] <= num[now+1])
                now = Right[now+1];
            Right[i] = now;
        }

        //右减左加1就是该柱形为中心形成的最大的矩形块的长
        ll sum = 0,Max = 0;
        for(ll i=1;i<=n;i++)
        {
            sum = (Right[i] - Left[i] + 1) * num[i];
            if(sum > Max)
                Max = sum;
        }
        printf("%lld
",Max);
    }
}


原文地址:https://www.cnblogs.com/GoldenFingers/p/9107327.html