A 最大矩形
题目描述:
给一个直方图,求直方图中的最大矩形的面积。例如,下面这个图片中直方图的高度从左到右分别是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
解题思路:
我们要找到,左右两边最后一个比a[i]大的位置,R和L,然后以它作为高,R-L+1作为他的宽,计算出矩形面积
1.寻找R
若要找右边最后一个比他大的位置,则,我们找到右边第一个比它小的位置-1,就能得到
我们利用单调栈来解决,当我们往栈内插入数值时,若栈顶元素>待插入元素
这时我们就要pop掉栈顶的元素维护单调,那么此时的栈顶元素就是第一个比他小的元素位置,-1则就是最后一个比他大的位置
当我们都插入完成,并且栈不为空的话,则表示留在栈内的元素,在其右侧没有比他小的元素,它可以扩展到n
2.寻找L
与R同理,将数组从n开始遍历到1,但与R不同的是,如果我们向左找到了第一个比它小的位置,求最后一个比她大的位置时是==+1==(左右分清)
而且当栈不为空时,说明他的左边没有比他大的,则,栈内的元素不能扩展,赋值1
接下来就比较简单啦,只需要不停的求出面积,算出最大就好了(这里还有一个要注意的地方,就是面积的计算有可能会超 所以要把ans定义成long long形式,计算的时候也要转换
#include<iostream>
#include<stdio.h>
using namespace std;
const int N=100010;
int n,a[N],R[N],L[N],st[N];
void solveR()
{
int l=1, r=0;
for(int i=1;i<=n;i++)
{
while(l<=r && a[st[r]] > a[i])
{
R[st[r]] = i-1;
r--;
}
st[++r] = i;
}
while(r>=0)
{
R[st[r]]=n;
r--;
}
}
void solveL()
{
int l=1, r=0;
for(int i=n;i>=1;i--)
{
while(l<=r && a[st[r]] > a[i])
{
L[st[r]] = i+1;
r--;
}
st[++r] = i;
}
while(r>=0)
{
L[st[r]]=1;
r--;
}
}
int main()
{
cin>>n;
while(n!=0)
{
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
solveR();
solveL();
// for(int i=1;i<=n;i++)
// cout<<R[i]<<" ";
// cout<<endl;
// for(int i=1;i<=n;i++)
// cout<<L[i]<<" ";
long long ans=0;
for(int i=1;i<=n;i++)
{
if(ans<(long long)a[i]*(R[i]-L[i]+1))
ans=(long long)a[i]*(R[i]-L[i]+1);
}
cout<<ans<<endl;
cin>>n;
}
return 0;
}