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

题目分析:

要求直方图中的最大矩形的面积,根据矩形面积公式在已知高度的前提下,必须要求出矩形的宽度,而在直方图中 矩形高度以[l,r]区间最小高度为准,矩形宽度=l-r+1。所以该题关键在于如何确定适合的l,r作为区间。

  • 要使整个矩形最大,那么高度就确定为l到r中的最小值。

  • 同理,如果确定了矩形的高度,那么左端点一定是越靠左, 右端点越靠右,这个矩形的面积才可能最大。

  • 左端点可以确定为往左数第一个小于此高度的点。

  • 右端点可以确定为往右数第一个小于此高度的点。

  • 单调栈中栈内元素自栈顶到栈底满足单调性。

    • 单调递增栈 可以找到往左/往右第一个比当前元素 大 的 元素 。
    • 单调递减栈 可以找到往左/往右第一个比当前元素 小 的 元素 。
    分别用单调递增栈和单调递减栈求出以每个点为高时的左右端点。

wa了很多次,原因在于数据类型,题给高度取值范围 0 <= hi <= 1000000000,虽然hi的范围不会超出int范围,但是在求取面积的过程中h和(l-r+1)相乘爆了int范围,所以会wa,所以需要将运算中的其中一个强转为long long类型的,在这里我将高度和面积都转换成了long long型的。嘤 long long 对应lld哦,别忘了(我就是忘了又多wa了一次 唉)

代码:

#include<iostream>
#include<stdio.h> 
#include<stack>
using namespace std;
const int maxn=1e5+100;
long long  L[maxn],R[maxn],w[maxn],a[maxn];
int n;
void solve()//找出各点右端点
{	
	stack<int> sa; 
	int l=1;int r=0;
	for(int i=1;i<=n;i++)
	{
		while(sa.size()>0 &&a[sa.top()]>a[i] )//单调递减栈找出右边第一个比当前元素小的元素
		{
			R[sa.top()]=i-1;
			sa.pop(); 
		} 
		sa.push(i);
	}
	while(sa.size()>0)//单调栈里的元素赋区间最右端点
	{
		R[sa.top()]=n;
		sa.pop();
	}
}
void solve1()//找出各点左端点
{	

	stack<int> sa; 
	int l=1;int r=0;
	//while(n--)
	for(int i=n;i>=1;i--)
	{
		while(sa.size()>0 &&a[sa.top()]>a[i] )//单调递减栈找出左边第一个比当前元素小的元素
		{
			L[sa.top()]=i+1;
			sa.pop(); 
		} 
		sa.push(i);
	}
	while(sa.size()>0)//单调栈里的元素赋区间最左端点
	{
		L[sa.top()]=1;
		sa.pop();
	}
}

int main()
{	
	//int n;//直方图小矩形个数 
	while(scanf("%d",&n)!=EOF)
	{
		if(n==0)
		{
			return 0;
		}	
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
		}
		solve(); 
		solve1();
		long long ans=0;
		for(int i=1;i<=n;i++)//计算面积
		{
			w[i]=a[i]*(R[i]-L[i]+1);
		}
		for(int i=1;i<=n;i++)//找出最大面积
		{
			if(w[i]>ans)
			{
				ans=w[i];
			}
		}
		printf("%lld\n",ans);
	} 
	return 0;	
} 
发布了21 篇原创文章 · 获赞 0 · 访问量 1096

猜你喜欢

转载自blog.csdn.net/qq_43746837/article/details/105012659