题意
有n个矩形,它们在一条水平线上且宽度都为1,长度分别为a[i]。求其中的最大子矩阵。
思考过程
我们从左往右枚举每一个矩形,第i个矩形依次尝试宽度为1~n-i+1,记录最低高度和最大面积。这个可以实现。
我们发现,其中的很多状态是包含的,导致我们做了很多无用的尝试。
事实上,对于一个相同的高度,我们希望它尽量宽,
题解
单调栈
建立一个单调递增栈,因为一个高度低的潜力更大,所以我们把它压到栈更深的地方。
对于一个大于栈顶的高度,我们直接放到栈顶上,记下这个位置。
如果小于栈顶,就要一直出栈直到大于栈顶的高度。弹出时计算一下以sta[top].h为高,以sta[top].p~i-1为宽的矩形的面积,看看要不要更新ans。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100010;
int n;
int a[maxn];
struct S
{
int h,p;//h高度 p位置
}sta[maxn];int top;
int main()
{
while(scanf("%d",&n),n!=0)
{
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
long long ans=0;
top=0;
for(int i=1;i<=n;i++)
{
int p=i;
while(a[i]<=sta[top].h && top!=0)
{
ans=max(ans,(long long)sta[top].h*(i-sta[top].p));//计算矩形面积
p=sta[top].p;//p记录最远的位置
top--;
}
sta[++top]=(S){a[i],p};
}
while(top!=0)//把所有留在栈内的矩阵计算一下
{
ans=max(ans,(long long)sta[top].h*(n+1-sta[top].p));
top--;
}
printf("%lld\n",ans);
}
return 0;
}