POJ:2556 Largest Rectangle in a Histogram

单调栈的应用。

思路类似于之前做得一个题,L【i】,R【i】,H【i】分别表示长度为H【i】的长方形的左端点和右端点。显然最大面积等于max{H【i】*(R【i】-L【i】+1)}。

H【i】已知,问题在于L【i】,R【i】怎么求。这里用那个题的思路就不行了。就左端点而言,这里需要求从当前位置i往左第一个长度小于H【i】的。这里可以用一个栈来维护。

如果栈顶长度大于等于H【i】则L【i】即i,否则将栈顶元素岀栈直到栈顶为空或者小于H【i】。栈空说明栈里所有元素都比H【i】大或者相等,则L【i】=1,如果栈顶元素小于H【i】,那么H【i】即栈顶当前元素对应位置。然后将当前位置元素入栈。

 为什么这样是正确的呢。因为栈始终是单调非减的。栈顶始终是最大的。但凡在该位置时岀栈的,一定是大于等于当前位置长度的。如果下一个位置的长度比当前位置长度要小,它自然也比之前岀栈这些要小。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <cmath>
#include <stack>
#include <queue>
#include <algorithm>
#define ll long long
#define INF 2139062143
#define inf -2139062144
#define MOD 20071027
#define MAXN 100005
using namespace std;
ll h[MAXN],L[MAXN],R[MAXN];
int main()
{
    int n;
    while(scanf("%d",&n)&&n)
    {

        for(int i=1; i<=n; ++i)
            scanf("%lld",&h[i]);
        L[1]=1;
        R[n]=n;
        stack<int> left;
        left.push(1);
        int t;
        for(int i=2; i<=n; ++i)
        {
            while(!left.empty()&&h[left.top()]>=h[i]) left.pop();
            if(left.empty()) L[i]=1;
            else L[i]=left.top()+1;
            left.push(i);
        }
        stack<int> right;
        right.push(n);
        for(int i=n-1; i>=1; --i)
        {
            while(!right.empty()&&h[right.top()]>=h[i]) right.pop();
            if(right.empty()) R[i]=n;
            else  R[i]=right.top()-1;
            right.push(i);
        }
        ll ans=0;
        for(int i=1; i<=n; ++i)
            ans=max(ans,h[i]*(R[i]-L[i]+1));
        printf("%lld\n",ans);
    }
    return 0;
}


你可能感兴趣的:(POJ:2556 Largest Rectangle in a Histogram)