NC50965 Largest Rectangle in a Histogram

题目

题目描述

A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rectangles have equal widths but may have different heights. For example, the figure on the left shows the histogram that consists of rectangles with the heights 2, 1, 4, 5, 1, 3, 3, measured in units where 1 is the width of the rectangles:



Usually, histograms are used to represent discrete distributions, e.g., the frequencies of characters in texts. Note that the order of the rectangles, i.e., their heights, is important. Calculate the area of the largest rectangle in a histogram that is aligned at the common base line, too. The figure on the right shows the largest aligned rectangle for the depicted histogram.

输入描述

The input contains several test cases. Each test case describes a histogram and starts with an integer n, denoting the number of rectangles it is composed of. You may assume that \(1 \leq n \leq 100000\) . Then follow n integers \(h1\dots hn\), where \(0 \leq h_i \leq 1000000000\). These numbers denote the heights of the rectangles of the histogram in left-to-right order. The width of each rectangle is 1. A zero follows the input for the last test case.

输出描述

For each test case output on a single line the area of the largest rectangle in the specified histogram. Remember that this rectangle must be aligned at the common base line.

示例1

输入

7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0

输出

8
4000

说明

Huge input, scanf is recommended.

题解

思路

知识点:单调栈。

如果枚举区间,获取区间最小直方,显然是很复杂的。因为区间不同导致的最小值不同,虽然可以用单调队列动态获取某一区间的最小值,但问题在于端点的可能有 \(n^2\) 个,所以复杂度是 \(O(n^2)\) 是不可接受的。

但是换一种角度,我们枚举直方,一共就 \(n\) 个,枚举 \(n\) 次即可。那么固定一个直方,最大的可伸展长度取决于左右第一个小于它的位置,找到长度乘以直方高度就是矩形面积了。

对于一个直方,左边最邻近小于用单调递增栈从左到右维护,右边同理从右到左维护,注意找到的位置是小于的那个直方的位置,而不是可伸展最大的位置,因此左边的需要加一,右边的需要减一。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>

using namespace std;

int h[100007];
int l[100007], r[100007];
///最大矩形高度肯定是某个矩形高度
///对于一个矩形,水平扩展距离取决于第一个比他小的,两边都是
///于是对每个矩形,用单调递增栈获得他左侧/右侧第一个比它小的矩形位置,就能知道左侧/右侧扩展距离
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
while (cin >> n, n) {
for (int i = 0;i < n;i++) cin >> h[i];
stack<int> s1;
for (int i = 0;i < n;i++) {
while (!s1.empty() && h[s1.top()] >= h[i]) s1.pop();
l[i] = s1.empty() ? 0 : s1.top() + 1;///左侧大于等于的第一个位置
s1.push(i);
}
stack<int> s2;
for (int i = n - 1;i >= 0;i--) {
while (!s2.empty() && h[s2.top()] >= h[i]) s2.pop();///一定是大于等于,于是栈就是严格递减栈,元素是最靠右的
r[i] = s2.empty() ? n - 1 : s2.top() - 1;///右侧大于等于的最后一个位置
s2.push(i);
}
long long ans = 0;
for (int i = 0;i < n;i++)
ans = max(ans, (r[i] - l[i] + 1LL) * h[i]);
cout << ans << '\n';
}
return 0;
}

最新文章

  1. 可轮播滚动的Tab选项卡
  2. W3School-CSS 伪类 (Pseudo-classes) 实例
  3. 【深入理解计算机系统02】ISA 与内存模型
  4. event相关
  5. C语言 在VS环境下一个很有意思的报错:stack around the variable was corrupted
  6. linux 下find命令 --查找文件名
  7. 设置Linux系统的LANG变量
  8. 开源虚拟化KVM(二)管理虚拟存储
  9. win32控制台程序 宽字符与短字符转化
  10. AI - 框架(Frameworks)
  11. 【XSY1642】Another Boring Problem 树上莫队
  12. [转载] apache ab压力测试报错(apr_socket_recv: Connection reset by peer (104))
  13. 如何抓取Amazon大图
  14. Swift3翻天覆地的改变
  15. IIS 7.0 SSL 部署指南
  16. scp 链接文件的问题 + tar
  17. 内网渗透中SSh的巧用
  18. 模拟登陆CSDN——就是这么简单
  19. 转-oracle中比较两表表结构差异和数据差异的方法
  20. Numpy:np.vstack()&amp;np.hstack() flat/flatten

热门文章

  1. C# 中托管内存与非托管内存之间的转换
  2. jsp第二周作业
  3. Runable与Callable的区别
  4. Infrastructure 知识: dnf对module的处理
  5. netty系列之:netty中的frame解码器
  6. 1.17 想学好Linux,这些习惯必须养成(初学者必读)
  7. ts中 any、unknown、never 、void的区别
  8. vue - Vue路由
  9. BFC 是什么?
  10. mysqldump速查手册