WEEK5 作业A - 最大矩形

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

题解

  • 采用单调递减栈的思想。
  • 数组h存放输入的各小矩形的高度,数组R表示小矩形右边第一个比他矮的矩形的下标,数组L表示小矩形左边第一个比他矮的矩形的下标,stack用来表示栈。
  • 循环n次,每次都把当前h[i]的下标i压入栈中,压栈时,因为要为维持单调递减栈,所以要把i前面比他高的都弹出栈。弹栈时,要弹出来的元素stack[r]的右边第一个比它小的元素即为当前要压入的元素(因为比它大的元素入栈时不会将它弹出,只有第一个比它小的会将它弹出),所以R[stack[r]]=i,左边第一个比它小的元素即为栈中它的前一个元素(因为比它大的元素在它入栈时都被弹出了),所以L[stack[r]]=stack[r-1]。弹栈完成后(栈为空或栈顶元素比要压入元素小),将i压入栈中。
  • 将所有元素都压入栈中后,弹出栈中剩下的元素(右边界为n,左边界为栈中它的前一个)。然后计算每个i对应的大矩形的面积,找出最大值并输出。

坑点

注意数据大小,long long 。

代码

#include <iostream>
#include <stdio.h>
using namespace std;
long long h[100100];
int stack[100100],R[100100],L[100100];
//stack存放的是对应的h下标 
int main(int argc, char** argv) {
	int n;
	while(1){
		scanf("%d",&n);
		if(n==0){break;}
		for(int i=0;i<n;i++){
			scanf("%lld",&h[i]);
		}
		int l=1,r=0;//从栈顶到栈底递减 
		stack[0]=-1;
		for(int i=0;i<n;i++){
			while(r>=l&&h[i]<h[stack[r]]){//需要弹栈 
				R[stack[r]]=i;
				L[stack[r]]=stack[r-1];
				r--;
			}
			//入栈
			r++; 
			stack[r]=i;
		}
		while(r>=l){//弹出栈中剩下的 
			R[stack[r]]=n;
			L[stack[r]]= stack[r-1];
			r--;
		}
		//计算最大矩形
		long long area=0;
		for(int i=0;i<n;i++){
			long long tmp=h[i]*(R[i]-L[i]-1);
			if(tmp>area){
				area=tmp;
			}
		} 
		printf("%lld\n",area);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值