题目大意:
题目链接:http://poj.org/problem?id=2559
给出一个直方图,在不超过其边界且要求底边和高分别平行于第和最左边直方图的高的情况下,找到其中的最大面积长方形。
本题由多组数据。
思路:
思路一:
先枚举每一个直方图,再直接暴力左右扩展边界,直到无法扩展为止。时间复杂度,十分不优秀。
思路二:
先用求出每个区间的最小值,然后再枚举每一个直方图,利用最小值求出左右边界。时间复杂度$O(t\times nlogn),依旧不优秀。
思路三:
考虑利用栈并且保持栈的单调性,当时,就不断掉,并求出最大值。时间复杂度,优秀。
while (q.size()&&a[q.top()]>a[i])
{
sum+=b[q.top()];
ans=max(ans,sum*a[q.top()]);
q.pop();
}
代码:
#include <cstdio>
#include <stack>
#include <iostream>
#include <cstring>
#define N 100100
using namespace std;
long long ans,sum,a[N+1],b[N+1];
int n;
stack<long long> q;
int main()
{
while (1)
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
ans=sum=0;
while (q.size()) q.pop(); //初始化
scanf("%d",&n);
if (!n) return 0;
for (int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
q.push(1);
b[1]=1; //先将第一个图放入栈
for (int i=2;i<=n+1;i++)
{
if (q.size()&&a[q.top()]<=a[i]) //保持单调
{
q.push(i);
b[i]=1; //宽度
}
else
{
sum=0;
while (q.size()&&a[q.top()]>a[i]) //不单调
{
sum+=b[q.top()]; //增加宽度
ans=max(ans,sum*a[q.top()]);
q.pop();
}
q.push(i);
b[q.top()]=sum+1; //宽度
}
}
cout<<ans<<endl;
}
return 0;
}