传送门:Largest Rectangle in a Histogram
题意
给定一系列高为 hi,宽为 1 的矩形,找出这些矩形组成的图形中最大的矩形面积。
思路
要求最大的矩形面积,我们只要知道以每个矩形的高度向右最远能够延申到的宽度,将这个宽度乘以高度就是它的面积,找出其中最大的一个就是我们要求的值。要得到这个宽度,我们可以采用一个单调递减栈(每次压栈的值都比栈顶的值大),并利用一个 startPos 维护以某个高度 h 最远能向左延申到的下标(最左最右本质上是相同的,目的都是求出宽度)。每次弹栈时,由于我们知道栈顶的高度必定比当前要压栈的高度要大,所以当前高度就能够延申到栈顶的高度最左能够延申到的下标。于是,为了维护栈的单调性,最后一个出栈的高度最左能够延申到的下标,就是当前要压栈的高度最左能够延申到的下标。每次弹栈求出栈顶的高度最左能延申到的面积,更新最大值。
当所有高度都遍历过一遍后,栈中可能还会有剩余的矩形未处理。这时,我们就把它们全部弹出,当前下标就是 n,弹出时计算面积,更新最大值即可。
代码
#include <iostream>
#include <cstdio>
#include <stack>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e5+5;
struct Node
{
ll height;
int startPos; //该高度能向左延申到的坐标
Node() {}
Node(ll height, int startPos): height(height), startPos(startPos) {}
};
int n;
stack<Node> monoStack;
ll h, ans;
void solve()
{
ans = 0;
monoStack.push(Node(-1, 0));
for(int i = 0; i < n; ++i)
{
scanf("%I64d", &h);
ll height;
int startPos = INF;
while(!monoStack.empty() && h <= monoStack.top().height)
{
height = monoStack.top().height;
startPos = monoStack.top().startPos;
monoStack.pop();
ans = max(ans, (ll)(i - startPos)*height);
}
monoStack.push(Node(h, min(i, startPos))); //最后一个出栈的startpos就是h最左能延申到的位置,如果没有出栈的,那就是i本身
}
while(!monoStack.empty()) //最后将所有结点弹出
{
ans = max(ans, (ll)(n - monoStack.top().startPos)*monoStack.top().height);
monoStack.pop();
}
printf("%I64d\n", ans);
}
int main()
{
while(scanf("%d", &n) && n)
{
solve();
}
return 0;
}