最大矩形面积(单调栈解法,我在此题探索到了许多)

目录

》题目《

》思路《

》代码《


》题目《

在X轴上水平放置着 N 个条形图,这 N 个条形图就组成了一个柱状图,每个条形图都是一个矩形,每个矩形都有相同的宽度,均为1单位长度,但是它们的高度并不相同。例如下图,图1包含的矩形的高分别为2,1,4,5,1,3,3 单位长度,矩形的宽为1单位长度。

你的任务就是计算柱状图中以X轴为底边的最大矩形的面积。图2阴影部分就是上述例子的最大矩形面积

》输入《

输入数据的第一行是一个整数 N(1≤ N ≤100000),表示柱状图包含 N 个矩形。紧接着 N 个整数h1,...,hn(0≤ hi ≤20000, 1≤ i≤ N),表示柱状图中按从左到右顺序给出的矩形的高度。矩形的宽度为1。

》输出《

最大矩形的面积

》样例输入《

7
2 1 4 5 1 3 3

》样例输出《

8

》思路《

大多数读者一眼就看出了这是最大矩形,怎么搞?怎么搞?

首先,我们思考一下每个矩形是如何来的

是不是以每栋建筑的高度为矩形的一边,再寻找另一边的长度(是的)

如何寻找另一边呢?

是不是左边第一个比这个建筑低的位置(左边界)右边第一个比这个建筑低的位置 (右边界)之间的距离(翻回去看,是不是?)

如何搞?

单调队列就很有用了。

首先,如果这个元素要入队(必须进去,别问我为什么),就要维护此队列的单调性(从栈底到栈顶(非)递增(减))

这道题就要用递增序列了(为什么后面会讲)

怎么求左边界呢?

试想:h[i-1] > h[i],是不是以 h[i-1] 为一边的矩形的右边界已经确定(因为已经不可能再往右延伸了嘛)

那么以 h[i] 为一边的矩形的左边界就要向左移一位(即 h[i] 的右边界更新成 i-1)

而这时 h[i-1] 已经已经没用了,所以我们就可以计算以 h[i-1] 为一边的矩形的面积,而它的右边界是不是就是 h[i] 的位置?

以它为一边的矩形的面积是不是就是 (h[i]的位置 - h[i-1]的位置)*h[i]。

所以,每当后一个建筑的高度小于前一个的高度时,就要把前一个建筑弹出去,更新位置(是不是单调递增的?)

至于细节嘛,自己想(cuo)去吧

》代码《

#include <stack>
#include <cstdio>
#include <iostream>
using namespace std;
 
struct node{
    int p, zhi;
}a[100005], b;
 
stack<node> t;
 
int ans, n;
 
int main(){
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++){
        scanf("%d", &a[i].zhi);
        a[i].p = i;
    }
    t.push(a[1]);
    for(int i = 2; i <= n; i ++){
        int pp = a[i].p;
        while( !t.empty() && t.top().zhi > a[i].zhi ){
            b = t.top();
            t.pop();
            a[i].p = b.p;
            int big = (pp - b.p) * b.zhi;
            ans = max(big ,ans);
        }
        t.push(a[i]);
    }
    while( !t.empty() ){
        b = t.top();
        t.pop();
        int big = (n + 1 - b.p) * b.zhi;
        ans = max(big ,ans);
    }
    printf("%d\n",ans);
    return 0;
}
 

欢迎读者补充与交流

猜你喜欢

转载自blog.csdn.net/zyz_bz/article/details/84873869