Largest Rectangle in a Histogram POJ - 2559

连接:Largest Rectangle in a Histogram POJ - 2559

大概题意

有n个高不一样的长方形(宽都是1)组成的柱状图,问你这个柱状图可以组成的面积最大的子矩形是多大。

思路

首先说一下朴素的算法:我们考虑其中一个矩形设这个矩形的高为x,我们想要以x为高组成面积最大的矩形,那么我们要扫描左边比x高的点可以延伸到最远的距离L1,再扫描右边比x高的点可以延伸的最远的距离L2。对每一个高度都要向左向右扫描,这样时间复杂度就非常的高。

所以可以用单调栈来优化时间:
考虑其中一个高度x,我们把栈内比这个高度高的点都出栈(这里相当于扫描左边比x高的点最远可以延伸的距离)每次出栈,对于出栈后的栈顶元素来说,就相当于扫描比栈顶元素高的右边可以延伸的最远的而距离。

说起来好像非常的绕,那就模拟一下吧,就用样例当例子吧
2 1 4 5 1 3 3

第一次入栈 :

2先入栈,这时栈内元素只有2

第二次入栈:

这时要入栈的元素为1,比较栈顶元素2,2大于1,(这里我们相当于发现左边比1高的点
这个时候我们要将2出栈。然后这个时候2的左边是没有比2大的数字的,这时候记录最大的矩形面积的值,也就是2*1=2;
这时栈内元素为1

第三次入栈:

这时我们要入栈的元素是4,4是大于此时的栈顶元素1的,直接入栈
此时的栈内元素为4 1

第四次入栈:

这时我们要入栈的元素是5,5大于此时的栈顶元素4,直接入栈
此时的栈内元素是5 4 1

第五次入栈:(手动画重点

这时我们要入栈的元素是1
比较栈顶元素5,5是大于1的,所以要将5出栈
再比较栈顶元素4,4是大于1的,所以也要将4出栈,可是在4出栈之前5已经出栈了,所以这里相当于扫描了4这个元素右边比4高的可以延伸的最远的距离(在4出栈之前,只有一个元素5出栈了,所以4的右边可以延伸的最远比4高的元素是1个
然而这个出栈对于要入栈的1而言,相当于扫描了1的左边有多少个比1高的元素

下面的入栈和出栈就和上面模拟的一样啦,就不赘述了。。
上代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stack>
using namespace std;
int a[100005];
typedef pair<long long,long long>p;
stack<p>s;
int main()
{
    int n;
    long long x;
    while(~scanf("%d",&n))
    {
        if(n==0)
            break;
        long long ans=0;
        for(int i=1; i<=n; i++)
        {
            scanf("%lld",&x);
            long long w=0;
            while(!s.empty()&&s.top().first>x)
            {
                long long a1=s.top().first;
                long long a2=s.top().second;
                s.pop();
                w=w+a2;//这里的w相当于对于a1来讲右边比a1高的可以延伸的最远距离
                ans=max(ans,w*a1);
            }
            s.push(make_pair(x,w+1));//这里入栈的第二个元素就相当于x左边比x高的最远可以延伸的距离
        }
        long long w=0;
        while(!s.empty())
        {
            long long a1=s.top().first;
            long long a2=s.top().second;
            w+=a2;
            s.pop();
            ans=max(ans,a1*w);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值