题意:
给一个直方图,求直方图中最大矩形的面积。输入包含多组数据,每组数据用一个整数n(1<=n<=100000)来表示直方图中小矩形的个数,然后接下来n个整数h1~hn,满足0<=hi<=1000000000。这些数字表示直方图中从左到右每个小矩形的高度,每个小矩形的宽度为1.测试数据以0结尾。
思路:
对每个小矩形的高度,求出该高度对应的左端点与右端点。左端点l为往左数第一个小于此高度的点,右端点r为往右数第一个小于此高度的点。
求左右端点可以使用单调栈来处理。如右端点,每当要加入的小矩形高度小于栈顶高度,则取出栈顶,将其对应的矩形的右端点设为当前要加入的小矩形的坐标。注意最后栈可能不为空,需要将里面所有的矩形右端点设为n。左端点同理。最后可以算出矩形的宽度为r-l-1。
还要注意,最后的面积会爆int,应使用long long int。
总结:
一道关于单调栈的应用题。在数据范围上有点小坑。以后遇见大数据范围可以直接开long long,不要小气,内存够用。
代码:
#include <iostream>
#include <stack>
using namespace std;
int n;
long long int ans;
int l[100000],r[100000]; //左端点与右端点
struct point
{
int index;
long long int h; //不开long long,之后求面积时会出错
}p[100000];
stack<point> s;
int main()
{
while(1)
{
cin>>n;
if(n==0) break;
for(int i=0;i<n;i++)
{
p[i].index=i;
cin>>p[i].h;
}
ans=0;
//处理右端点
for(int i=0;i<n;i++)
{//往右数第一个小于h[i]的点
while(s.size()>0&&s.top().h>p[i].h)
{
point now=s.top();
s.pop();
r[now.index]=i;
}
s.push(p[i]);
}
//最后栈可能不为空,里面的矩形右端点为n
while(!s.empty())
{
point now=s.top();
s.pop();
r[now.index]=n;
}
//处理左端点
for(int i=n-1;i>=0;i--)
{//往左数第一个小于h[i]的点
while(s.size()>0&&s.top().h>p[i].h)
{
point now=s.top();
s.pop();
l[now.index]=i;
}
s.push(p[i]);
}
//最后栈可能不为空,里面的矩形左端点为-1
while(!s.empty())
{
point now=s.top();
s.pop();
l[now.index]=-1;
}
//长度为r-l-1
for(int i=0;i<n;i++)
{
long long int mianji=p[i].h*(r[i]-l[i]-1);
if(mianji>ans) ans=mianji;
}
cout<<ans<<endl;
}
}