Description
A histogram is a polygon composed of a sequence of rectangles aligned at a common base line. The rectangles have equal widths but may have different heights. For example, the figure on the left shows the histogram that consists of rectangles with the heights 2, 1, 4, 5, 1, 3, 3, measured in units where 1 is the width of the rectangles:
Usually, histograms are used to represent discrete distributions, e.g., the frequencies of characters in texts. Note that the order of the rectangles, i.e., their heights, is important. Calculate the area of the largest rectangle in a histogram that is aligned at the common base line, too. The figure on the right shows the largest aligned rectangle for the depicted histogram.
Input
The input contains several test cases. Each test case describes a histogram and starts with an integer n, denoting the number of rectangles it is composed of. You may assume that 1<=n<=100000. Then follow n integers h1,…,hn, where 0<=hi<=1000000000. These numbers denote the heights of the rectangles of the histogram in left-to-right order. The width of each rectangle is 1. A zero follows the input for the last test case.
Output
For each test case output on a single line the area of the largest rectangle in the specified histogram. Remember that this rectangle must be aligned at the common base line.
Sample Input
7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0
Sample Output
8
4000
题解:
针对于2这个矩形条,我们希望求得的最大面积是从4一直到5的长度,
针对于6的最大面积是6到7的长度,
3的最大面积是6到5(2)…
通过这个规律可以看出,例如求3的最大面积,我们是从2之后6这个矩形条开始一直到1之前的5(2)结束,因此2,3,5,5是个单调不降子序列。
因此,我们要维护一个单调不降的栈,一旦遇到一个元素小于栈顶元素,那么就把大于当前元素的之前矩形条对应的最大面积都求出来,然后把当前元素入栈。
比如当前元素是1,2,3,5,5为原来栈中元素, 1比栈顶元素5(2)小,因此求5(2)前一个比它小的数3之后的数5(1)和后一个比它小的数1之前的数5(2)的长度,求出面积是5*1;弹栈;
1还比5(1)小,再求5(1)前一个比它小的数3之后的数5(1)自己和后一个比它小的数1之前的数5(2)的面积时5 * 2;弹栈;
栈顶元素3还大于1,再次求3前一个比它小的数2之后的数6和后一个比它小的数1之前的数5(2)的面积3 * 5=15.
1还小于栈顶2,继续求2前一个比它小的数0(a[sk]初始化为0,并且矩形条的高度都是整数)和后一个比它小的数(末尾0)的面积1*10;
最后末尾加一个0,可以求出整个矩形面积(秒啊)。
总结:维护一个单调不降队列,当要求面积的时候,需要求当前矩阵条对应的最大面积的宽度,则是该队列的队头位置到该矩阵条的位置之间的距离。所以每次要求这样的一个宽度时,就要维护一个单调队列。
再给几组测试数据可以模拟一下刚才描述的过程:
5
1 2 3 4 4
9
10
3 4 5 1 4 5 7 3 6 2
15
7
2 1 4 5 1 3 3
8
4
1000 1000 1000 1000
4000
10
5 4 3 1 4 5 7 3 6 2
15
看代码:
#include<iostream>//维护一个单调递增,妙~
#include<cstdio>
#include<cstring>
using namespace std;
long long mx,a[100005],n=1,top,sk[100005];
int work()
{
top=1;//
sk[top]=1;//
for(int i=2;i<=n;i++)
{
while(a[sk[top]]>a[i] )
{
mx=max(mx,a[sk[top]]*(i-sk[top-1]-1));
top--;
}
sk[++top]=i;
}
return mx;
}
int main()
{
while(scanf("%d",&n) && n)
{
memset(a,0,sizeof a);
memset(sk,0,sizeof sk);
mx=0;
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
a[++n]=0;//最后输入一个0,将所有矩形都弹栈
work();
printf("%I64d\n",mx);
}
}