题目描述:
最近,afy 决定给 TOJ 印刷广告,广告牌是刷在城市的建筑物上的,城市里有紧靠着的 n n n 个建筑。afy 决定在上面找一块尽可能大的矩形放置广告牌。我们假设每个建筑物都有一个高度,从左到右给出每个建筑物的高度 h 1 h_1 h1, h 2 h_2 h2,…, h n h_n hn,且 0 0 0 < h i h_i hi ≤ 1 , 000 , 000 , 000 1,000,000,000 1,000,000,000,并且我们假设每个建筑物的宽度均为 1 1 1。要求输出广告牌的最大面积。
输入格式:
第一行是一个数 n n n( n n n ≤ 1000 , 000 1000,000 1000,000)。
第二行是 n n n 个数,分别表示每个建筑物高度 h 1 h_1 h1, h 2 h_2 h2,…, h n h_n hn,且 0 0 0 < h i h_i hi ≤ 1 , 000 , 000 , 000 1,000,000,000 1,000,000,000。
输出格式:
输出文件共有一行,表示广告牌的最大面积。
样例数据:
输入
6
5 8 4 4 8 4
输出
24
题目意思很简单,方法也很容易想到,对于每栋建筑物,都分别找出左边和右边第一个高度小于它的建筑物(假设位置分别为 l l l 和 r r r),那么从 l + 1 l+1 l+1 到 r − 1 r-1 r−1 的高度都大于等于它,此时的最优解为 h ∗ ( r − l − 1 ) h*(r-l-1) h∗(r−l−1),扫一遍统计最大值即可
如何找 l , r l,r l,r 呢?我们用单调栈(单调递增)来找,每次加入一个数,都把在栈中大于等于它的数弹出去,那么第一个小于它的位置就在栈顶。正着做一遍求 l l l,返着做一遍求 r r r 就可以啦
注意输入量比较大,建议加读优
#include
#include
#include
#include
#define N 1000005
using namespace std;
int h[N],L[N],R[N];
stack<int>s;
int main()
{
int n,i;
long long Max=0;
scanf("%d",&n);
for(i=1;i<=n;++i)
scanf("%d",&h[i]);
for(i=1;i<=n;++i)
{
while(!s.empty()&&h[i]<=h[s.top()]) s.pop();
L[i]=(s.empty()?1:s.top()+1);s.push(i);
}
while(!s.empty()) s.pop();
for(i=n;i>=1;--i)
{
while(!s.empty()&&h[i]<=h[s.top()]) s.pop();
R[i]=(s.empty()?n:s.top()-1);s.push(i);
}
for(i=1;i<=n;++i)
Max=max(Max,1ll*h[i]*(R[i]-L[i]+1));
printf("%lld",Max);
return 0;
}