最大矩形(单调队列)

问题描述

给一个直方图,求直方图中的最大矩形的面积。例如,下面这个图片中直方图的高度从左到右分别是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

问题分析

这个题目如果只是简单暴力的话时间复杂度太高,不能AC,需要借助一种神奇的数据结构——单调队列=单调+队列=队列中的元素满足出队顺序的单调性,实现O(n)的时间复杂度解决问题,利用队列分别找到每一个位置向左/向右的数都大于等于他的最远位置。(向左最远位置-向右最远位置+1)*高得到矩形的面积,我们需要枚举每个位置进行上述操作,找到最大矩形。
代码如下:

#include<stdio.h>
long long h[100005];
int st[100005],L[100005],R[100005];
void solve(int n)
{
	int l=1,r=0;
	long long max=0;
	st[0]=0;
	for(int i=1;i<=n;i++)
	{
		while(l<=r && h[st[r]]>h[i])
		{
			R[st[r--]]=i-1;
		}	
		L[i]=st[r]+1;
		st[++r]=i;
	}
	for(int i=l;i<=r;i++)
		R[st[i]]=n;
	for(int i=1;i<=n;i++)
		if((R[i]-L[i]+1)*h[i]>max)
		max=(R[i]-L[i]+1)*h[i];
	printf("%lld\n",max);		
}
int main()
{
	int n;
	scanf("%d",&n);
	while(n)
	{
		for(int i=1;i<=n;i++)scanf("%d",&h[i]);
		solve(n);
		scanf("%d",&n); 
	}
	return 0;
 } 
发布了19 篇原创文章 · 获赞 0 · 访问量 508

猜你喜欢

转载自blog.csdn.net/YingMila/article/details/105231176