【Week5作业 A】最大矩形【单调栈】

题意:

给一个直方图,求直方图中最大矩形的面积。输入包含多组数据,每组数据用一个整数n(1<=n<=100000)来表示直方图中小矩形的个数,然后接下来n个整数h1~hn,满足0<=hi<=1000000000。这些数字表示直方图中从左到右每个小矩形的高度,每个小矩形的宽度为1.测试数据以0结尾。


思路:

对每个小矩形的高度,求出该高度对应的左端点与右端点。左端点l为往左数第一个小于此高度的点,右端点r为往右数第一个小于此高度的点。
求左右端点可以使用单调栈来处理。如右端点,每当要加入的小矩形高度小于栈顶高度,则取出栈顶,将其对应的矩形的右端点设为当前要加入的小矩形的坐标。注意最后栈可能不为空,需要将里面所有的矩形右端点设为n。左端点同理。最后可以算出矩形的宽度为r-l-1。
还要注意,最后的面积会爆int,应使用long long int。


总结:

一道关于单调栈的应用题。在数据范围上有点小坑。以后遇见大数据范围可以直接开long long,不要小气,内存够用。


代码:

#include <iostream>
#include <stack>
using namespace std;

int n;
long long int ans;
int l[100000],r[100000];	//左端点与右端点 
struct point
{
	int index;
	long long int h;	//不开long long,之后求面积时会出错 
}p[100000];
stack<point> s;
int main()
{
	while(1)
	{
		cin>>n;
		if(n==0)	break;
		for(int i=0;i<n;i++)
		{
			p[i].index=i;
			cin>>p[i].h;
		}
		ans=0;
		//处理右端点 
		for(int i=0;i<n;i++)
		{//往右数第一个小于h[i]的点 
			while(s.size()>0&&s.top().h>p[i].h)
			{
				point now=s.top();
				s.pop();
				r[now.index]=i;
			}
			s.push(p[i]);
		}
		//最后栈可能不为空,里面的矩形右端点为n 
		while(!s.empty())
		{
			point now=s.top();
			s.pop();
			r[now.index]=n;
		}
		//处理左端点 
		for(int i=n-1;i>=0;i--)
		{//往左数第一个小于h[i]的点	 
			while(s.size()>0&&s.top().h>p[i].h)
			{
				point now=s.top();
				s.pop();
				l[now.index]=i;
			}
			s.push(p[i]);
		}
		//最后栈可能不为空,里面的矩形左端点为-1
		while(!s.empty())
		{
			point now=s.top();
			s.pop();
			l[now.index]=-1;
		}
		//长度为r-l-1
		for(int i=0;i<n;i++)
		{
			long long int mianji=p[i].h*(r[i]-l[i]-1);
			if(mianji>ans)	ans=mianji;
		} 
		cout<<ans<<endl;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值