POJ2559 Largest Rectangle in a Histogram

版权声明:转载带上我的名字哦 https://blog.csdn.net/zezzezzez/article/details/81409211

Largest Rectangle in a Histogram

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 25861   Accepted: 8377

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.

题意:给出一个图有几个矩形组成,矩形的宽都是一,高不定,计算几个连续的矩形包含的最大面积。

思路:这个题是个单调栈,我们每次枚举每个矩形向左和向右延伸的最大程度,最大程度的延伸能够保持面积的最大,例如

8 10 2,我们依次放出单调栈,8,10,当10放进去时,我们发现8向左不能延伸,向右可以延伸1位(10里边可以放的下),当2放进去时10向左不可以延伸,向右也不可以延伸,我们当做向右包括他自己算一位。2的话可以向左延伸,不可以向右延伸,并且我们在出现退栈的时候才计算,单调栈要保持单调性,所以要依次退栈,这样我们就可以在加入2的时候把8,10退栈的时候以此计算8和10的向左向右延展程度。

我开始自己写的那个代码有点丑,就是两个for依次算出向左还有向右的值。看了大佬博客发现一个for就可以了

大佬博客:https://www.cnblogs.com/WABoss/p/5225464.html         

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
int a[100005];
int sta[100005];//数组模拟单调栈
int r[100005];//向右看
int l[100005];//向左看
int main()
{
    int n,top;
    while(~scanf("%d",&n)&&n)
    {
        memset(a,0,sizeof(a));
        memset(sta,0,sizeof(sta));
        for(int i=1; i<=n; i++)
            scanf("%d",&a[i]);
        top=0;
        a[++n]=-1;//要把最后一位变成-1,这样可以保证都是递增序列不出现退栈时也可以计算
        for(int i=1; i<=n; i++)
        {
            l[i]=i;
            r[i]=i;
            while(top&&a[sta[top]]>a[i])//当出现退栈的时候,a[i]都比top的小,那么top向右不能延伸,自己就可以算一次,而a[i]就可以向左延伸
            {
                r[sta[top]]=i-1;//记录此时向右的延伸到哪
                l[i]=l[sta[top]];//记录此时向左的延伸到哪
                top--;
            }
            if(top&&a[sta[top]]==a[i])//相同时就直接明了,a[i]向左延伸就好了
            {
                l[i]=l[sta[top]];
            }
            sta[++top]=i;
        }
        ll ans=0;
        for(int i=1; i<n; i++)
        {
            ans=max(ans,(ll)(r[i]-l[i]+1)*a[i]);
//            printf("%d %d %d\n",r[i],l[i],ans);
        }
        printf("%lld\n",ans);
    }
}


                                                                                               

猜你喜欢

转载自blog.csdn.net/zezzezzez/article/details/81409211