直方图是由在公共基线处对齐的一系列矩形组成的多边形。
矩形具有相等的宽度,但可以具有不同的高度。
例如,图例左侧显示了由高度为 2,1,4,5,1,3,32,1,4,5,1,3,3 的矩形组成的直方图,矩形的宽度都为 11:
通常,直方图用于表示离散分布,例如,文本中字符的频率。
现在,请你计算在公共基线处对齐的直方图中最大矩形的面积。
图例右图显示了所描绘直方图的最大对齐矩形。
思路如下
遍历每个矩形将其向左右伸展直到左右高度都小于当前高度,此为当前矩形最大面积。求出所有遍历面积中最大面积。
知识点及其实现
单调栈
依次将每一个高度读入栈中,每次进行遍历的时候当遇到左边高度大于当前高度时就将栈尾删去(因为当下一次遍历的时候无论其高度多少都不会用到这个元素)。
用单调栈有这个好处:这个维护的是其q[i]始终是i的左边的最小高度的编号。
(疏于语言只能描述成这样)
以下为代码
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 1e5;
int n;
int q[N], h[N], l[N], r[N];
//单调栈的实现
void get(int a[N]){
int tt = 0;
for(int i = 1;i <= n;i ++){
while(h[q[tt]] >= h[i]) tt --;
a[i] = q[tt];
q[++ tt] = i;
}
}
int main(){
h[0] = -1;
while(cin >> n, n){
for(int i = 1;i <= n;i ++) scanf("%d", &h[i]);
get(l);
reverse(h + 1, h + n + 1);
get(r);
LL res = 0;
for(int i = 1,j = n;i <= n;i ++,j --){
res = max(res, h[i] * (n + 1 - l[j] - r[i] - 1ll));//小难点reverse后下标i转换成n — i + 1而r[i]于l[n - 1 + 1]对应即
//要转换两次
}
cout << res << endl;
}
}