直方图中最大的矩形(单调栈)

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

矩形具有相等的宽度,但可以具有不同的高度
链接
图不知道怎么弄
例如,图例左侧显示了由高度为2,1,4,5,1,3,3的矩形组成的直方图,矩形的宽度都为1:
通常,直方图用于表示离散分布,例如,文本中字符的频率。
现在,请你计算在公共基线处对齐的直方图中最大矩形的面积。
图例右图显示了所描绘直方图的最大对齐矩形。
输入格式
输入包含几个测试用例。
每个测试用例占据一行,用以描述一个直方图,并以整数n开始,表示组成直方图的矩形数目。
然后跟随n个整数h1,…,hn。
这些数字以从左到右的顺序表示直方图的各个矩形的高度。
每个矩形的宽度为1。
同行数字用空格隔开。
当输入用例为n=0时,结束输入,且该用例不用考虑。
输出格式
对于每一个测试用例,输出一个整数,代表指定直方图中最大矩形的区域面积。
每个数据占一行。
请注意,此矩形必须在公共基线处对齐。
数据范围
1≤n≤100000,
0≤hi≤1000000000
输入:
7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0
输出:
8
4000

分析,可取一个长方形条,然后该长方形条的左右两边高度大于等于它的即可把该矩形面积扩大,故转换为求该长方形条左右两边第一个比它小的长方形条位置;即为单调栈;这里运用两个单调栈,有很多写法,我的写法如下:
c++代码如下;

#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const int mod = 999911659;
const int N = 100009;
typedef pair<int,int> pii;
stack<int> sal,sar;
int a[N],bl[N],br[N];
int main(){

	int n;
	while(cin>>n&&n)
	{
		memset(bl,0,sizeof bl);
		memset(br,0,sizeof br);
		while(sar.size()) sar.pop();
		while(sal.size()) sal.pop();
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];//求右边
			while(sar.size() && a[sar.top()] >= a[i])
			{
				br[sar.top()]=i;
				sar.pop();
			}
			sar.push(i);
			//求左边
			while(sal.size() && a[sal.top()] >= a[i]) sal.pop();
			if(sal.size() && a[sal.top()] < a[i]) bl[i]=sal.top();
			sal.push(i);
		}
//		for(int i=1;i<=n;i++) cout<<bl[i]<<" ";cout<<endl;
//		for(int i=1;i<=n;i++) cout<<br[i]<<" ";cout<<endl;
		ll ma=0,sum=0;
		for(int i=1;i<=n;i++)
		{
			if(br[i]==0) br[i]=n+1;//右边为0即它没有比它还小的
			sum=a[i]*(br[i]-bl[i]-1ll);//这里要转换成ll型
			ma=max(sum,ma);
		}
		cout<<ma<<endl;
	}
	return 0;
}

有问题还请联系,谢谢
进阶练习这里

下面是使用单调栈求解直方图最大矩形面积的C++完整代码: ```c++ #include <iostream> #include <stack> using namespace std; int getMaxArea(int hist[], int n) { stack<int> stk; int maxArea = 0, area = 0, i = 0; while (i < n) { if (stk.empty() || hist[stk.top()] <= hist[i]) { stk.push(i++); } else { int top = stk.top(); stk.pop(); area = hist[top] * (stk.empty() ? i : i - stk.top() - 1); if (area > maxArea) { maxArea = area; } } } while (!stk.empty()) { int top = stk.top(); stk.pop(); area = hist[top] * (stk.empty() ? i : i - stk.top() - 1); if (area > maxArea) { maxArea = area; } } return maxArea; } int main() { int hist[] = {6, 2, 5, 4, 5, 1, 6}; int n = sizeof(hist) / sizeof(hist[0]); cout << "The maximum area of the histogram is " << getMaxArea(hist, n) << endl; return 0; } ``` 在上述代码,我们使用一个单调栈来维护直方图的柱子。具体来说,我们从左到右遍历直方图的柱子,如果当前柱子的高度不小于栈顶柱子的高度,则将当前柱子入栈;否则,我们弹出栈顶柱子,计算以该柱子高度为最小高度的矩形面积,更新最大面积值。在弹出栈顶柱子之后,当前柱子继续与栈顶柱子比较,直到当前柱子的高度不小于栈顶柱子的高度或者栈为空为止。 当所有的柱子都遍历完成后,我们需要将栈剩余的柱子依次弹出,并根据弹出柱子的高度计算以该高度为最小高度的矩形面积,再次更新最大面积值。 最后,我们返回最大面积值即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值