题意

现在有一个柱状图,告诉你每一个,柱子的宽度和高度,然后问你这个图里最大的矩形面积,这里的矩形可以是这样的

图片说明
也可以是这样的
图片说明
这样就很好理解了。就是找其中出现了的最大的矩形。

解析

这个题目用到了单调栈这个数据结构,简单描述一下就是栈里面的元素呈单调递增或者单调递减,并不难理解,如果是递增的,那么栈顶元素即是最大的,这个题目为什么用这个,举个例子

图片说明
像这样的一个柱状图,我们肯定要穷举每一个可能组成的矩形然后来比较大小,我们可以从最左边开始,
第一列

图片说明
第二列

图片说明
到了第三列
就要比较这两个了
图片说明

图片说明
第四列也是这样

那么到了第五列呢,第五列比前面的更矮,我们在记录前面的最大值之后,在第五列(如果后面还有)就用不到第五列前并且比第五列高的地方了,因为第五列只能和他一样高的组成矩形,比他高或者比他矮都不行

那么我们现在在储存的时候,在计算完最大值之后,遇到了更矮的,前面的高的就没必要存下来了,这样子就形成了一个单调增的栈,(为什么是栈,因为比他高的都依次出栈,然后把他作为最高的)

然后我们只要手写一个栈,模拟进栈出栈就好了,
遇到比栈顶高的和他相同的直接压进栈,遇到比他矮的就将栈里比他高的全部出栈,然后维护一下宽度就好了

有一个点要注意,就是在最后一个之后再压一个0进栈,因为如果最后几个是递增或者相同的情况,在我的代码里是有问题的,我的代码里如果没有元素出栈就不会去计算矩阵的大小,

ps:数据有点太弱了,最好不压一个0进栈也能过,一开始我看大佬的代码还以为是我的理解错了。。。。结果是大佬的笔误。。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1e6+7;

ll w[MAXN],h[MAXN];
ll st_h[MAXN],st_w[MAXN],top;

int main(void){
    int n,m;
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
        scanf("%lld",&w[i]);
    for(int i=1;i<=n;++i)
        scanf("%lld",&h[i]);

    h[n+1]=w[n+1]=top=0;
    ll ans=0;
    for(int i=1;i<=n+1;++i){
        if(h[i]>=st_h[top]){
            top++;
            st_h[top]=h[i];
            st_w[top]=w[i];
        }
        else{
            ll width=0;
            while(top && h[i]<=st_h[top]){
                width+=st_w[top];
                ans=max(ans,width*st_h[top]);
                top--;
            }
            top++;
            st_h[top]=h[i];
            st_w[top]=width+w[i];
        }
    }
    printf("%lld\n",ans);
    return 0;
}