《算法竞赛进阶指南》0x11 T4 Largest Rectangle in a Histogram

题目传送门

题目描述

直方图是由在公共基线处对齐的一系列矩形组成的多边形。

矩形具有相等的宽度,但可以具有不同的高度。

例如,图例左侧显示了由高度为 2 , 1 , 4 , 5 , 1 , 3 , 3 2,1,4,5,1,3,3 2,1,4,5,1,3,3 的矩形组成的直方图,矩形的宽度都为 1 1 1
《算法竞赛进阶指南》0x11 T4 Largest Rectangle in a Histogram_第1张图片
通常,直方图用于表示离散分布,例如,文本中字符的频率。

现在,请你计算在公共基线处对齐的直方图中最大矩形的面积。

图例右图显示了所描绘直方图的最大对齐矩形。

题解

这道题目需要利用到单调栈的思想,单调栈的思想见《数据结构》博客中
对于每一个位置,我们只需要扫描以这个位置上的高度,向左能扩展几格,向右能扩展几格,最后扩展出的矩形就是以它的高度和位置能做出的最大价值

所以对于每一个位置,我们用单调栈去寻找它左侧第一个比它低的位置和右侧第一个比它低的位置,这两个位置即为当前位置最大高度能扩展出的最大矩形边界(左右两个方向用到了两次单调栈)
对于每个点都进行一次单调栈的操作,扩大的矩阵长度*矩阵高度即为它的贡献值,每个点的贡献值中的最大值即为答案

也就是说对n个点进行上述操作,每次操作的复杂度也为 O ( n ) O(n) O(n)
总复杂度是 O ( n 2 ) O(n^2) O(n2)的,可以完成本题

code
#include
using namespace std;
int n;
const int N=1e5+10;
int a[N],l[N],r[N];
stack<int> s;
int main()
{
	while(1)
	{
		scanf("%d",&n);
		if(n==0) return 0;
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
		while(s.size()) s.pop();
		for(int i=1;i<=n;i++) 
		{
			int t=0;
			while(s.size())
			{
				int x=s.top();
				if(a[i]<=a[x]) s.pop();
				else
				{
					t=x;
					break;
				 } 
			}
			s.push(i);
			l[i]=t+1;
		}
		while(s.size()) s.pop();
		for(int i=n;i>=1;i--) 
		{
			int t=n+1;
			while(s.size())
			{
				int x=s.top();
				if(a[i]<=a[x]) s.pop();
				else
				{
					t=x;
					break;
				 } 
			}
			s.push(i);
			r[i]=t-1;
		}
		long long ans=-1;
		for(int i=1;i<=n;i++) ans=max(ans,1ll*(r[i]-l[i]+1)*a[i]);
		printf("%lld\n",ans);
	}
	return 0;
}

你可能感兴趣的:(算法竞赛进阶指南,栈,c++)