week5A 单调栈求矩形最大面积

题意:

给定一个直方图,求这个直方图中的矩形的最大面积。
如图阴影位最大面积:
在这里插入图片描述
input:

输入多组数据,每组数据的第一行位直方图中单位矩形的个数,其后跟着的n个数据即为每个单位矩形的高度。

output:

对每组数据输出其中能组成的矩形的最大的面积。

思路:

利用单调递增栈,可用数据来作为栈,用一个top变量作为栈指针。找出每个单位矩形的左边和右边第一个比它矮的矩形的位置,单调栈中保存每个矩形的下标索引。即得到该单位矩阵所能达到的最大的宽度。其中单调栈的实现,即从第一个单位矩形开始,依次加入单调栈,如果加入的时候,单调栈位空或者比栈顶元素大的时候入栈,栈为空的时候该矩形的左边边界到达1,不为空的时候即到达单调栈中栈顶的数据的位置,(注意要判断其单调栈栈顶的数据是否和要加入的数据相同,如果相同,则左端点为该相同元素的左端点,虽然这一点对最终要求的结果没有影响),即在入栈的时候确定好每个点的左端点。如果要加入栈数据比栈顶的数据小,则要弹栈,即top不断减小,直到栈为空或者比栈顶元素大的时候,可以入栈,入栈时,可以得到左端点。在弹栈的时候可以保存下右端点。在最后所有的点都入栈后,即可得到一个完全单调的栈,栈顶的数据,即为栈中所有数据的右端点,全部出栈,即可得到右端点。在入栈和出栈的操作中便可得到左右端点,与该点的高度相乘可以得到以这个高度的矩形的面积。最后输出最大面积即可。

总结:

有很多要注意的小细节,特别时要用long long,一个Int让我找了老长时间的bug。

代码:

#include <cstdio>

long long y1[100005];  //作为单调栈存
int top=0;    //栈顶指针 

struct P{
	long long num;  
	long long l;
	long long r;
};
P p[100005];


int main(){
	int n;
	scanf("%lld",&n);  
	 
	while(n!=0){
		for(int i=1; i<=n; i++){  //读入数据 
			scanf("%lld",&p[i].num);		
		}
		
		top=0;
		int j=1;  //当前要入栈的数据序号 
		while( j<=n ){  
			if(top==0 || p[j].num>=p[y1[top]].num){  //入栈记录左边 
			
				if(top>0){
					if(p[j].num==p[y1[top]].num ){
						p[j].l=p[y1[top]].l;
			 		}else{
						p[j].l=y1[top]+1;
					}
				}else{
					p[j].l=1;
				}			
				top++;
				y1[top]=j;
				j++;
			}else{
				while(p[y1[top]].num>p[j].num && top>0){  //有出栈 
					p[y1[top]].r=j-1;			  //记录右端点	
					top--;
				}
				
				if(top>0){
					if(p[j].num==p[y1[top]].num ){
						p[j].l=p[y1[top]].l;
			 		}else{
						p[j].l=y1[top]+1;
					}
				}else{
					p[j].l=1;
				}	
				top++;
				y1[top]=j;
				j++;			
			}
		}
		
		//单调不减
		int lastR=y1[top];
		while(top>0){
			p[y1[top]].r=lastR;
			top--;
		}
		
		
		long long max=0;
		long long now=0;
		for(int i=1; i<=n; i++){
			now=p[i].num*(p[i].r-p[i].l+1);
			if(now>max) max=now;
		}
		printf("%lld\n",max);
		scanf("%lld",&n);
	} 

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值