题目:
给一个直方图,求直方图中的最大矩形的面积。例如,下面这个图片中直方图的高度从左到右分别是2, 1, 4, 5, 1, 3, 3, 他们的宽都是1,其中最大的矩形是阴影部分。
输入:
输入包含多组数据。每组数据用一个整数n来表示直方图中小矩形的个数,你可以假定1 <= n <= 100000. 然后接下来n个整数h1, …, hn, 满足 0 <= hi <= 1000000000. 这些数字表示直方图中从左到右每个小矩形的高度,每个小矩形的宽度为1。 测试数据以0结尾。
输出:
对于每组测试数据输出一行一个整数表示答案。
样例输入:
7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0
样例输出:
8
4000
本题用单调栈解决。
遇到栈顶元素小于当前元素,或者栈为空时将元素压入栈。
遇到栈顶元素大于当前元素时,把栈顶元素弹出,然后根据弹出元素的高度及其元素序号来更新最大面积;继续判断,直到栈顶元素小于当前元素。
压入栈的都是元素的序号,这样可以通过当前元素的序号i,弹出元素的序号left,弹出元素的高度nowheight,得到新的面积nowheight×(i-left-1)。
此外,虽然单个数据都在int的数据范围内,但是最后的面积会超过int的范围,所以用long long类型的数据。
以下是完整代码:
#include<iostream>
#include<stack>
using namespace std;
long long height[200000];
long long max(long long x,long long y)
{
if(x>y)
{
return x;
}
else
{
return y;
}
}
void solve(int n)
{
long long ans=0;
long long nowHeight;
stack<long long> s;
for(int i=0;i<=n;i++)
{
while(!s.empty()&&height[s.top()]>height[i])//当前元素小于栈顶元素
{
nowHeight=height[s.top()];
s.pop();
int left;
if(s.empty())
{
left=-1;
}
else
{
left=s.top();
}
ans=max(ans,nowHeight*(i-left-1));//更新面积 ans
}
s.push(i);
}
cout<<ans<<'\n';
}
int main()
{
int n;
while(1)
{
cin>>n;
if(n==0)
{
break;
}
for(int i=0;i<200000;i++)
{
height[i]=0;
}
for(int i=0;i<n;i++)
{
cin>>height[i];
}
solve(n);
}
}