问题描述
给一个直方图,求直方图中的最大矩形的面积。例如,下面这个图片中直方图的高度从左到右分别是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
问题分析
这个题目如果只是简单暴力的话时间复杂度太高,不能AC,需要借助一种神奇的数据结构——单调队列=单调+队列=队列中的元素满足出队顺序的单调性,实现O(n)的时间复杂度解决问题,利用队列分别找到每一个位置向左/向右的数都大于等于他的最远位置。(向左最远位置-向右最远位置+1)*高得到矩形的面积,我们需要枚举每个位置进行上述操作,找到最大矩形。
代码如下:
#include<stdio.h>
long long h[100005];
int st[100005],L[100005],R[100005];
void solve(int n)
{
int l=1,r=0;
long long max=0;
st[0]=0;
for(int i=1;i<=n;i++)
{
while(l<=r && h[st[r]]>h[i])
{
R[st[r--]]=i-1;
}
L[i]=st[r]+1;
st[++r]=i;
}
for(int i=l;i<=r;i++)
R[st[i]]=n;
for(int i=1;i<=n;i++)
if((R[i]-L[i]+1)*h[i]>max)
max=(R[i]-L[i]+1)*h[i];
printf("%lld\n",max);
}
int main()
{
int n;
scanf("%d",&n);
while(n)
{
for(int i=1;i<=n;i++)scanf("%d",&h[i]);
solve(n);
scanf("%d",&n);
}
return 0;
}