WEEK 5 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]向左右扩散,可以到达的最左点为l,最右点为r,则该点的最大矩形的面积为a[i]*(r-l+1);根据题意,左边界l是满足a[j-1] < a[i]的最大的j,即从i点向左遍历的第一个高度比i小的点的右边一个点,而右边界r是满足a[j+1] < a[i]的最小的j,即从i点向右遍历第一个高度比i小的点的左边一个点。所以我们可以利用单调栈的性质不断得到确定点,即确定高度的最大面积矩形的左右边界。

代码:

#include <iostream>
#include <stack>
#include <algorithm>

using namespace std;

stack<int> s;
const int N = 1e6+10;
long long n, ans;
long long a[N], R[N], L[N];

void solvel()
{
	while (s.size() != 0)
		s.pop();
	for (int i = 1; i <= n; i++)
	{
		while (s.size() != 0 && a[s.top()] >= a[i])
			s.pop();
		if (s.empty())
			L[i] = 1;
		else
			L[i] = s.top() + 1;
		s.push(i);
	}
}

void solver()
{
	while (s.size() != 0)
		s.pop();
	for (int i = n; i >= 1; i--)
	{
		while (s.size() != 0 && a[s.top()] >= a[i])
			s.pop();
		if (s.empty())
			R[i] = n;
		else
			R[i] = s.top() - 1;
		s.push(i);
	}
}

int main()
{
	while (scanf_s("%d",&n)!=EOF)
	{
		if (n == 0)
			break;
		ans = 0;
		for (int i = 1; i <= n; i++)
			scanf_s("%d", &a[i]);
		solver();
		solvel();
		for (int i = 1; i <= n; i++)
			ans = max(ans, a[i] * (R[i] - L[i] + 1));
		cout << ans << endl;
	}
    return 0; 
}
发布了32 篇原创文章 · 获赞 0 · 访问量 685

猜你喜欢

转载自blog.csdn.net/qq_43814559/article/details/105000595
今日推荐