题意
给一个直方图,求直方图中的最大矩形的面积。例如,下面这个图片中直方图的高度从左到右分别是2, 1, 4, 5, 1, 3, 3, 他们的宽都是1,其中最大的矩形是阴影部分。
Input
输入包含多组数据。每组数据用一个整数n来表示直方图中小矩形的个数,你可以假定1 <= n <= 100000. 然后接下来n个整数h1, …, hn, 满足 0 <= hi <= 1000000000. 这些数字表示直方图中从左到右每个小矩形的高度,每个小矩形的宽度为1。 测试数据以0结尾。
Output
对于每组测试数据输出一行一个整数表示答案。
Sample Input
7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0
Sample Output
8
4000
思路
本题使用单调栈来接替,对于每一个矩形,分别向左和向右运用单调栈来找到该矩形高度向左和向右可以延展的最大距离,最后再对每一个矩形求面积,比较出最大面积(具体请参考代码注释)
代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
using namespace std;
long long s[100010], h[100010], L[100010], R[100010];
void left(long long);//向左延展
void right(long long);//向右延展
int main()
{
long long n;
while (scanf("%lld", &n) != EOF && n != 0)
{
for (long long i = 1; i <= n; i++)
scanf("%lld", &h[i]);
//设置柱状图两侧为绝对小值,以求出柱状图边缘矩形的最大延展距离。
h[0] = -1;
h[n + 1] = -1;
left(n);
right(n);
long long max = 0;
for (long long i = 0; i <= n; i++)
{
long long len = R[i] - L[i] + 1;
long long area = len * h[i];
if (area > max)
max = area;
}
cout << max << endl;
}
return 0;
}
void left(long long n)
{
long long l = 0, r = -1;
for (long long i = n; i >= 0; i--)
{
while (l <= r && h[s[r]] > h[i])
{//新加入的高度低于最小高度
L[s[r]] = i + 1;//将栈顶元素所代表的矩形向左扩展的边界进行赋值
r--;//弹栈
}
s[++r] = i;//将新元素压入栈中
}
}
void right(long long n)
{
long long l = 0, r = -1;
for (long long i = 1; i <= n + 1; i++)
{
while (l <= r && h[s[r]] > h[i])
{//新加入的高度小于最小高度
R[s[r]] = i - 1;//将栈顶元素所代表的矩形向右扩展的边界进行赋值
r--;//弹栈
}
s[++r] = i;//将新元素压入栈中
}
}