poj 2559(栈的应用)
Posted violet-acmer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj 2559(栈的应用)相关的知识,希望对你有一定的参考价值。
https://www.cnblogs.com/violet-acmer/p/9780420.html
参考资料:
[1]:挑战程序设计竞赛
题意:
柱状图是由一些宽度相等的长方形下端对齐后横向排列得到的图形。现在有由n个宽度为1,高度分别为h[1,2,3.......n]的长方形从左到右依次排列组成的柱状图。
问里面包含的长方形的最大面积是多少?
题解:
如果确定了长方形的左端点L和右端点R,那么最大可能的高度就是min{h[i] | L <= i <= R}。这样我们就得到了一个O(N^3)的算法,如果对计算区间最小值进行一些优化,那么可以把复杂度将为O(N^2)。
但即使是这样,仍然无法在规定时间内求出答案。那么我们应该怎么做才能更高效的求解呢?
设面积最大的长方形左端是L,右端是R,高度是H。
易得H[L-1] < H 且 H[R+1] < H ,H=min{h[i] | L <= i <= R} 。
证明:
如果H[L-1] >= H ,那么左端点就可以更新为L-1,从而可以得到更大的长方形,与假设矛盾,因此 H[L-1] < H,同理可得 H[R+1] < H。
我们可以遍历一边,找到每个 i (i=1,2,3,......,n) 的最小的L[i]和最大的R[i],这样答案就是 max( h[i]*(R[i]-L[i]+1) ) (i=1,2,3,.........,n)。
关键就是如何在线性时间内求出每个 i 的 L[i]和R[i]。
由 H[L-1] < H && H[R+1] < H 可得:
L[i]=( i 之前的高度第一个小于 h[i] 对应的下标) + 1;
R[i]=( i 之后的高度第一个小于 h[i] 对应的下标) - 1;
暴力方法当然是对于每个 i 都遍历一边 i 之前的值和 i 之后的值,这当然是会超时的,所以,我们要换个思路。
引入一个新的数据结构栈:
在计算 L[i] 时,首先,判断栈顶元素 j 的高度 h[j] 是否大于等于 h[i],如果h[j] >= h[i],则不断弹出栈顶元素,直到 h[j] < h[i] 或栈为空。
若栈为空,则L[i] = 1,反之,L[i]=j+1,然后将 i 压入栈中。
计算 R[i] 时只需反向( i 从n 到 1 )重复上述过程即可。
由于栈的压入和弹出操作都是 O(N),因此整个算法的时间复杂度为 O(N);
AC代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<stack> 4 using namespace std; 5 const int maxn=1e5+50; 6 7 int n; 8 int h[maxn]; 9 int l[maxn],r[maxn]; 10 stack<int >_stack; 11 12 void Init() 13 { 14 while(!_stack.empty())//好几次将 while() 写成 if( ),然后,在主程序中找了半天Bug,emmmmmmmm 15 _stack.pop(); 16 } 17 int main() 18 { 19 while(scanf("%d",&n) && n) 20 { 21 Init(); 22 for(int i=1;i <= n;++i) 23 scanf("%d",h+i); 24 for(int i=1;i <= n;++i)//求 l[i] 25 { 26 while(!_stack.empty() && h[_stack.top()] >= h[i]) 27 _stack.pop(); 28 l[i]=(_stack.empty() ? 1:_stack.top()+1); 29 _stack.push(i); 30 } 31 Init();//一定要将栈清空 32 for(int i=n;i >= 1;--i)//求 r[i] 33 { 34 while(!_stack.empty() && h[_stack.top()] >= h[i]) 35 _stack.pop(); 36 r[i]=(_stack.empty() ? n:_stack.top()-1); 37 _stack.push(i); 38 } 39 long long res=0; 40 for(int i=1;i <= n;++i) 41 res=max(res,(long long)h[i]*(r[i]-l[i]+1)); 42 printf("%lld ",res); 43 } 44 return 0; 45 }
以上是关于poj 2559(栈的应用)的主要内容,如果未能解决你的问题,请参考以下文章
《算法竞赛进阶指南》0x11栈 单调栈求矩形面积 POJ2559
POJ 2559 Largest Rectangle in a Histogram ——笛卡尔树