【SOJ 393】广告印刷

【题目】

题目描述:

最近,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 r1 的高度都大于等于它,此时的最优解为 h ∗ ( r − l − 1 ) h*(r-l-1) h(rl1),扫一遍统计最大值即可

如何找 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;
}

你可能感兴趣的:(#,栈)