最大矩形
输入包含多组数据。每组数据用一个整数n来表示直方图中小矩形的个数,可以假定1 <= n <= 100000. 然后接下来n个整数h1, …, hn, 满足 0 <= hi <= 1000000000. 这些数字表示直方图中从左到右每个小矩形的高度,每个小矩形的宽度为1。 测试数据以0结尾。对于每组测试数据输出一行一个整数表示答案。
sample input:
7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0
sample output:
8
4000
思路:
- 显然最终的矩形大小=宽×高,高是一个矩形的高度,宽是这个矩形左至右遇到第一个比他矮的矩形所经过的矩形个数
- 根据这个思路其实可以用暴力,针对每一个矩形都向他的左右去寻找比他小的矩形,然后进行计算经过的宽度,但是由于给定的数据个数较多,可能会爆
- 对两边进行寻找比较麻烦,如果能首先将矩形进行从低到高的排列,那么只需要计算他的右边有多少个矩形,就可以算出当前的矩形面积。(因为低矩形不能计算宽度,这样就可以从双边变成单边)
- 这样就可以使用单调栈的思想,建立一个栈,栈内保存的矩形是高度递增的。为了到达目的,遍历每一个直方图矩形:如果当前矩形的高度比栈顶矩形的高度高,那么就将当前高度压栈;否则就弹出栈顶。
- 出栈时计算出累计的宽度值,计算出矩形的大小与答案进行比较,取较大值对答案进行更新;再将累计宽度和当前高度存入,进行压栈。
- 全部遍历后得到的ans就是最大的矩形面积,单调栈的时间复杂度只有O(n)
- 第一次使用了stack类型直接做,然后TLE了,所以用数组进行描述,添加一个int变量top相当于栈顶。需要注意的是本题的数据范围,ans和stack需要使用long long ,在max比较的时候需要将比较的变量化成统一数据类型,强制类型转换即可
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<stack>
using namespace std;
int main()
{
int n;
while(scanf("%d",&n)!=EOF&&n!=0)
{
int a[100011],w[100011];
long long stack[100011];
long long top=0;
long long ans=0;
memset(a,0,sizeof(a));
for(int i=0;i<n;i++) scanf("%d",&a[i]);
for(int i=0;i<=n;i++)
{
if(a[i]>stack[top])
{
stack[++top]=a[i];
w[top]=1;
}
else
{
int width=0;
while(stack[top]>a[i])
{
width+=w[top];
ans=max(ans,(long long)width*stack[top]);
top--;
}
top++;
stack[top]=a[i];
w[top]=width+1;
}
}
printf("%lld\n",ans);
}
return 0;
}