栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

AcWing 131. 直方图中最大的矩形(单调栈)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

AcWing 131. 直方图中最大的矩形(单调栈)

【题目描述】
直方图是由在公共基线处对齐的一系列矩形组成的多边形。
矩形具有相等的宽度,但可以具有不同的高度。
例如,图例左侧显示了由高度为 2 , 1 , 4 , 5 , 1 , 3 , 3 2,1,4,5,1,3,3 2,1,4,5,1,3,3的矩形组成的直方图,矩形的宽度都为 1 1 1:

通常,直方图用于表示离散分布,例如,文本中字符的频率。
现在,请你计算在公共基线处对齐的直方图中最大矩形的面积。
图例右图显示了所描绘直方图的最大对齐矩形。

【输入格式】
输入包含几个测试用例。
每个测试用例占据一行,用以描述一个直方图,并以整数 n n n开始,表示组成直方图的矩形数目。
然后跟随 n n n个整数 h 1 , … , h n h_1,dots ,h_n h1​,…,hn​。
这些数字以从左到右的顺序表示直方图的各个矩形的高度。
每个矩形的宽度为 1 1 1。
同行数字用空格隔开。
当输入用例为 n = 0 n=0 n=0时,结束输入,且该用例不用考虑。

【输出格式】
对于每一个测试用例,输出一个整数,代表指定直方图中最大矩形的区域面积。
每个数据占一行。
请注意,此矩形必须在公共基线处对齐。

【数据范围】
1 ≤ n ≤ 1 0 5 1≤n≤10^5 1≤n≤105
0 ≤ h i ≤ 1 0 9 0≤h_i≤10^9 0≤hi​≤109

【输入样例】

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

【输出样例】

8
4000

【分析】


如下图所示,我们枚举每个高度 h i h_i hi​,那么 i i i向左右延伸至第一个比 h i h_i hi​低的位置后一定能围出一个高度为 h i h_i hi​的面积最大的矩形,那么很容易想到复杂度为 O ( n 2 ) O(n^2) O(n2)的暴力做法,那么有什么数据结构能够优化复杂度呢?

找到某个数左边/右边第一个小于这个数的方式可以使用单调栈在 O ( n ) O(n) O(n)的时间复杂度预处理出来,因此我们可以使用 l [ i ] l[i] l[i]与 r [ i ] r[i] r[i]分别表示 i i i左边与右边第一个比 h i h_i hi​低的位置,正向与反向遍历一遍构造出相应的单调栈预处理出这两个数组,最后再枚举一遍所有 h i h_i hi​,答案在 h [ i ] ∗ ( r [ i ] − l [ i ] − 1 ) h[i]*(r[i]-l[i]-1) h[i]∗(r[i]−l[i]−1)中取最大值即可。


【代码】

#include 
#include 
#include 
using namespace std;

typedef long long LL;
const int N = 100010;
int h[N], l[N], r[N];//l/r[i]表示i左/右边第一个比h[i]低的位置
int stk[N], tt;
int n;

int main()
{
    while (cin >> n, n)
    {
        for (int i = 1; i <= n; i++) cin >> h[i];
        h[0] = h[n + 1] = -1;//初始化边界
        tt = 0, stk[0] = 0;
        for (int i = 1; i <= n; i++)
        {
            while (h[i] <= h[stk[tt]]) tt--;//由于存在边界所以栈一定非空
            l[i] = stk[tt];
            stk[++tt] = i;
        }
        tt = 0, stk[0] = n + 1;
        for (int i = n; i; i--)
        {
            while (h[i] <= h[stk[tt]]) tt--;
            r[i] = stk[tt];
            stk[++tt] = i;
        }
        LL res = 0;
        for (int i = 1; i <= n; i++) res = max(res, (LL)h[i] * (r[i] - l[i] - 1));
        cout << res << endl;
    }
    return 0;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/768811.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号