Largest Rectangle in a Histogram(POJ No.2559) (栈的运用)

本文介绍了一种高效算法,用于解决由不同高度矩形组成的柱形图中寻找最大矩形面积的问题。通过使用单调栈计算每个矩形左右边界,实现O(n)时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

题意:n个宽度为1,高度为h[i](1<=i<=n)组成的柱形图,求里面包含的长方形的最大面积;

思路:如果确定了长方形的左端点L和右端点R,那么最大可能高度就是min{h[i]|L<=i<R}(一般做题区间都是左闭右开,便于计算),时间复杂度O(n^3),考虑优化区间最小值,可以降为O(n^2),但仍然无法在规定时间内求出答案。
考虑换种思路假设面积最大的长方形的左端为L,右端为R,高度为H。如果h[L-1]>=H,那么左端点可以更新为L-1,从而得到更大的长方形,与假设矛盾,故h[L-1]<H。同理,h[R]<H,并且高度H=min{h[i]|L<=i<R}。
做法:我们可以固定h[i]向左右方向延伸,则可以定义两个单调栈:L[i]=(j<=i并且h[j-1]<h[i]的最大的j)   R[i]=(j<i并且h[j]>h[i]的最小的j)
在计算L[i]时,首先,当栈顶的元素j满足h[j]>=h[i],则不断取出栈顶元素。若栈为空,则L[i]=0,若h[j]<h[i],则L[i]=j+1.然后把i压入栈中。
时间复杂度:由于栈的压入和弹出操作都是O(n)次,因此整个算法的时间复杂度为O(n)。对于R也可以用同样的方法计算。


代码:
//输入
int n;
int h[maxn];


int L[maxn],R[maxn];
int st[maxn];//栈


void solve(){
    //计算L

    int top=0;//单调递减栈
    for(int i=0;i<n;i++)
    {

         while(top&&h[st[top]]>=h[i])  top--;//加入i时,判断栈顶值是否满足>=h[i]
         L[i]=top==0?0:(st[top]+1);
         st[++top]=i;
     }
       
    //计算R

    int top=0;//倒序单调递减栈
    for(int i=n-1;i>=0;i--)
    {
         while(top&&h[st[top]]>=h[i])  top--;//加入i时,判断栈顶值是否满足>=h[i]
         R[i]=top==0?n:st[top];
         st[++top]=i;
     }

     long long res=0;
     for(int i=0;i<n;i++)
           res=max(res,(long long)h[i]*(R[i]-L[i]));
     printf("%lld\n",res);

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值