poj 2559 Largest Rectangle in a Histogram(单调栈)

106 篇文章 0 订阅
64 篇文章 0 订阅

题意:

在二维坐标上,有n个相邻的矩形,每个矩形的宽为单位长度,高不相同,问能组成的最大子矩形面积。

配合图片使用更佳:


阴影部分即样例的最大矩形。


解题思路:

我们考虑每一个单位矩形,它能否以自己的高度和相邻的矩形组成一个新的矩形取决于旁边的矩形的高度是否不小于它,那么,我们如果能知道一个矩形左边第一个高度小于它的矩形的位置l,右边第一个高度小于它的矩形的位置r,那么我们就能知道以这个矩形的高为高能形成新的最大矩形的面积(r-l-1)*height。

那么怎么求出l,r呢,我们只需要从前往后,从后往前分别跑一遍单调栈(递增),就能维护出每一个矩形的l,r。

单调递增栈在压栈的时候,让栈顶开始所以高度大于等于自己的元素都出栈,这时候栈顶的元素就是第一个小于自己高度的元素了,就求出目标矩形的位置了,然后自己再入栈,继续维护。


代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#define LL long long
using namespace std;
const int maxn=1e5+5;
struct p
{
    LL height;
    LL l;
    LL r;
}a[maxn];
int in[maxn];
int main()
{
    int n, i, j;
    while(~scanf("%d", &n))
    {
        if(n==0)break;
        int top=0;
        for(i=0; i<n; i++)a[i].l=a[i].r=0;
        for(i=0; i<n; i++)
        {
            scanf("%lld", &a[i].height);
            if(top==0)
            {
                in[++top]=i;
                a[i].l=-1;   //左边没有值就是左边没有元素小于自己
            }
            else 
            {
                while(top>0 && a[in[top]].height>=a[i].height)
                {
                    top--;
                }
                
                if(top>0)a[i].l=in[top];
                else a[i].l=-1; //左边没有元素小于自己 
                in[++top]=i;
            }
        }
        top=0;
        for(i=n-1; i>=0; i--)
        {
            if(top==0)in[++top]=i, a[i].r=n;
            else 
            {
               while(top>0 && a[in[top]].height>=a[i].height)
               {
                    top--;
               }
               if(top>0)a[i].r=in[top];
               else a[i].r=n;
               in[++top]=i;
            }
        }
        LL x, ans=0;
        for(i=0; i<n; i++)
        {
    //        printf("%d %lld %lld\n", i, a[i].l, a[i].r);
            x=a[i].height*(a[i].r-a[i].l-1LL);
            ans=x>ans?x:ans;          
        }
        printf("%lld\n", ans);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值