题意
求
列的直方图中最大的矩形面积。
思路
单调栈入门题。首先不难发现,枚举了最低列后,向两边拓展,总的复杂度是 的。但是如果能用某种数据结构得到每一列向左和向右的第一个比它小的列号,就可以 的算答案了。不难发现,在单向扫描的过程中,如果遇到了一个较矮的列,那么前面更高的列肯定不会作为答案(因为更近而且高度更小),于是这一列可以把前面较矮的列换掉。由此,我们可以维护一个递增的序列,每次替换后就可以得到第一个比它小的列号了。此数据结构插入和删除都是从一个方向的,又能实时维护一个单调的序列。这种有栈的性质,保持序列单调以得到解的方法称为单调栈。单调栈的一种作用就是找到向左或向右第一个比它小的数的位置,栈内一般存下标。
代码
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<map>
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
#define N 100003
typedef long long LL;
using namespace std;
int a[N],L[N],R[N];
bool cmp(int x,int y){return x<y;} //建一个对于a数组,从栈底到栈顶单调性为cmp的单调栈,栈里存下标
template<int *a,bool cmp(int,int)>struct monostk
{ //单调栈模板
int stk[N],tp;
monostk(){tp=0;}
void clear(){tp=0;}
void del(int _){while(tp&&!cmp(a[stk[tp]],a[_]))tp--;}
void push(int _){stk[++tp]=_;}
int top(){return stk[tp];}
};
monostk<a,cmp>ms;
int main()
{
int n;
while(scanf("%d",&n),n)
{
FOR(i,1,n)scanf("%d",&a[i]);
ms.clear();
ms.stk[0]=0;
FOR(i,1,n)
{
ms.del(i);
L[i]=ms.top();
ms.push(i);
}
ms.clear();
ms.stk[0]=n+1;
DOR(i,n,1)
{
ms.del(i);
R[i]=ms.top();
ms.push(i);
}
LL ans=0;
FOR(i,1,n)ans=max(ans,1LL*(R[i]-L[i]-1)*a[i]);
printf("%lld\n",ans);
}
return 0;
}