Week5 作业 A - 最大矩形 HDU - 1506 单调栈

博客介绍了如何利用单调栈解决直方图中求最大矩形面积的问题。通过输入数据,进行左右两侧的单调栈遍历,找到能延伸的最大坐标,最终计算出最大面积,并提醒注意数据规模需使用`long long`类型存储结果。
摘要由CSDN通过智能技术生成
题目

给一个直方图,求直方图中的最大矩形的面积。例如,下面这个图片中直方图的高度从左到右分别是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
解题思路

由于单调栈具有更优的时间复杂度,本题用单调栈解,根据输入数据,分别从左往右、从右往左进行两次单调栈遍历,找出某个点能往左、往右延伸的最大坐标。最后计算面积,取最大值。本题需要注意数据大小,最后计算面积时需要开 long long 。

程序源码
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdio.h>
using namespace std;

int L[100005]{ 0 };
int result[100005]{ 0 };
int resul2[100005]{ 0 };
int stack[100005]{ 0 };
int posi[100005]{ 0 };

int main() {
	int n;
	while (scanf("%d", &n)) { //读取直方图中小矩形的个数n
		if (n == 0) {
			break;
		}
		for (int i = 0; i < n; i++) { //为结束符
			scanf("%d", &L[i]);
		}
		int point = 0, size = 0;
		for (int i = 0; i < n; i++) { //从左往右遍历
			while (size > 0 && stack[point] > L[i]) { //栈顶元素大于当前元素,出栈
				result[posi[point]] = i; //记录出栈位置
				point--;
				size--;
			}
			stack[++point] = L[i]; //入栈
			posi[point] = i; //记录当前栈对应的元素
			size++;
		}
		while (size > 0) { //取出栈中剩余元素
			result[posi[point]] = n; //记录出栈位置
			point--;
			size--;
		}
		point = 0, size = 0;
		for (int i = n - 1; i >= 0; i--) { //从右往左遍历
			while (size > 0 && stack[point] > L[i]) { //栈顶元素大于当前元素,出栈
				resul2[posi[point]] = i; //记录出栈位置
				point--;
				size--;
			}
			stack[++point] = L[i]; //入栈
			posi[point] = i; //记录当前栈对应的元素
			size++;
		}
		while (size > 0) { //取出栈中剩余元素
			resul2[posi[point]] = -1; //记录出栈位置
			point--;
			size--;
		}
		long long maxs = 0, curs = 0; //计算最大面积
		for (int i = 0; i < n; i++) { // 面积 = 高度 * (右端点 - 左端点 - 1)
			curs = (long long)L[i] * (long long)(result[i] - resul2[i] - 1);
			if (curs > maxs) { //取最大
				maxs = curs;
			}
		}
		cout << maxs << endl; //输出

	}
	return 0;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值