题意
现在有一个柱状图,告诉你每一个,柱子的宽度和高度,然后问你这个图里最大的矩形面积,这里的矩形可以是这样的
也可以是这样的
这样就很好理解了。就是找其中出现了的最大的矩形。
解析
这个题目用到了单调栈这个数据结构,简单描述一下就是栈里面的元素呈单调递增或者单调递减,并不难理解,如果是递增的,那么栈顶元素即是最大的,这个题目为什么用这个,举个例子
像这样的一个柱状图,我们肯定要穷举每一个可能组成的矩形然后来比较大小,我们可以从最左边开始,
第一列
第二列
到了第三列
就要比较这两个了
第四列也是这样
那么到了第五列呢,第五列比前面的更矮,我们在记录前面的最大值之后,在第五列(如果后面还有)就用不到第五列前并且比第五列高的地方了,因为第五列只能和他一样高的组成矩形,比他高或者比他矮都不行
那么我们现在在储存的时候,在计算完最大值之后,遇到了更矮的,前面的高的就没必要存下来了,这样子就形成了一个单调增的栈,(为什么是栈,因为比他高的都依次出栈,然后把他作为最高的)
然后我们只要手写一个栈,模拟进栈出栈就好了,
遇到比栈顶高的和他相同的直接压进栈,遇到比他矮的就将栈里比他高的全部出栈,然后维护一下宽度就好了
有一个点要注意,就是在最后一个之后再压一个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; }