HDU -1506 - Largest Rectangle in a Histogram(单调栈)

博客给出HDU 1506题的链接,介绍两种解题思路。思路一是利用单调栈预处理每个矩形高度左右边界,以当前高度为矩形高度求面积并取最大值;思路二是维护单调递增栈,在序列两端放最小值作边界,遇到比栈顶小的元素就计算栈内元素组成矩形面积并维护最大值。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1506

思路1:利用单调栈,可以找到从左 / 右遍历第一个比它小 / 大的元素的位置,我们可以用这个性质预处理每一个矩形高度左右边界(也就是第一个比当前高度小的元素的位置),当我们知道左右第一个比它小的数,去掉这两个比它小的,剩下的都是比它大的了,然后就可以用当前这个高度作为矩形的高度求面积,最后取个最大值即可。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define IOS cin.tie(0); cout.tie(0); ios::sync_with_stdio(0);
const int N = 1e5+7;
int n, a[N], l[N], r[N];
stack <int> s;
int main()
{
    IOS;
    while(cin >> n && n)
    {
        while(!s.empty()) s.pop();
        for(int i = 1; i <= n; i++) cin >> a[i];
        for(int i = 1; i <= n; i++)
        {
            while(s.size() && a[i] <= a[s.top()]) s.pop();
            if(!s.size()) l[i] = 0;
            else l[i] = s.top();
            s.push(i);
        }
        while(!s.empty()) s.pop();

        for(int i = n; i >= 1; i--)
        {
            while(s.size() && a[i] <= a[s.top()]) s.pop();
            if(!s.size()) r[i] = n + 1;
            else r[i] = s.top();
            s.push(i);
        }
        ll ans = 0;
        for(int i = 1; i <= n; i++)
            ans = max(ans, (ll)(r[i] - l[i] - 1) * a[i]);
        cout << ans << endl;
    }

}
/*
7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0
*/

思路2:维护一个单调递增栈,先在序列两端放两个最小值作为边界,然后遇到比栈顶小的元素就计算栈内元素能够组成的矩形面积并维护最大值即可。此题最小高度为0,所以要用比0小的数作为边界。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e5 + 7;
int n, h[N];
stack <int> s;
int main()
{
    while(~scanf("%d",&n) && n)
    {
        for (int i = 1; i <= n; i++)
            scanf("%d", &h[i]);
        h[0] = -1, h[n+1] = -1;
        s.push(0); ll ans = 0;
        for(int i = 1; i <= n + 1; i++)
        {
            while(h[i] < h[s.top()])
            {
                int index = s.top();
                s.pop();
                ll tmp = (ll)(i - 1 - s.top()) * h[index];
                ans = max(ans, tmp);
            }
            s.push(i);
        }
        printf("%lld\n",ans);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值