Largest Rectangle in a Histogram
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.
题目大意:哪一块联通的矩形面积最大
这个题目就是讲哪一块联通的矩形的面积最大,初看这个题目,并不知道在讲什么东西,什么乱七八糟的,最大的矩形面积?我自己都要算半天才知道哪一块面积最大,更何况还得遍出程序?
由于上课讲了这个题目,我就大概知道怎么算,这是要构建一个单调递增栈(非严格)。
解题思路1(错误的想法,但是值得一提):我们该如何做这道题呢?比如,我前N-1个矩形都是单增的现在要将第N个入栈,但是呢。。第N个很矮,假如就和第一个一样高吧!那么我在入栈的时候,前面的比它高自然要出栈喽,这时候这个矩形的面积要算一下哈,让这个矩形和MAX_S(MAX_S表示的是矩形的最大面积初始化的时候是0)来比较一下大小吧,假如这个矩形的面积大于MAX_S,那么我们就将MAX_S改成这个矩形的面积。但是这个大的矩形该何去何从呢?弹出吗?显然不可能对吧?毕竟我前面的矩形和我现在要入栈的矩形还可以联通不是吗?所以呢我们这个时候就将这个矩形变成一个更矮的矩形对吗?那要多矮才合适呢?这时候我们可以想到既然可以和左右联通,那么我这个加入的矩形变成一个和左右矩形大的那一个对吧?但改变了还不够,我现在虽然变矮了但是我这第一个还是要比现在要加入栈的要高,那这个时候该怎么办呢?那么,我们现在得需要用循环了,当我现在这个栈顶元素比要加入的元素要大的时候,我就一直将矩形变小,但是现在变小的不是一个了,而是一个区间内的矩形,这时候我们还要一重循环(这就是这个算法失败的地方,超时了)来将这个区间内的矩形全部变成和要加入的矩形的高度一样,但在这个过程中还需要不断更新MAX_S的值! 讲了这么大家肯定晕了对吗? 其实我也觉得很麻烦。。。
解题思路2:
我直接从刚刚那个程序失败的败笔来入手吧,我敲完我得代码一直超时,之后我就去问了学长怎么做这个题目,他说我循环写错了,用长度来表示相同高度的个数就好了,这个时候我们就可以在每个矩形入栈的时候记录一下它的长度,当然,开始都是1喽!,现在我们还是使用之前的案例吧,我前N-1个矩形都是单增的现在要将第N个入栈,但是呢。。第N个很矮,这个时候N-1不是比N要高吗?那么我们在算这个矩形面积的时候就变了变成 high*wide这样来算,high表示的时这个矩形的高度,wide表示的是这个矩形的长度,现在喽,N-1这个矩形已经算完了,那么我们只需要让N-2的宽度加上N-1这个矩形的宽度就好啦,之后,N-1这个矩形弹出;就这样,一直循环循环,一直循环,知道和N这个矩形矮或者相同结束就好了。。
到现在,应该大概知道我得意思了吧?
下面给出代码:
#include
#include
using namespace std;
#define max(a,b) a>b?a:b
struct stack{
long long a[100001];
int b[100001];
int top;
};
long long a[100001];
int main(void){
stack s;
int n,i,j,sum;
long long Max;
while(scanf("%d",&n)&&n){
for(i=0;is.a[s.top]){
s.a[++s.top]=a[i];
s.b[s.top]=1;
continue;
}
else{
while(s.a[s.top]>=a[i]){
if(s.top-1==-1){
Max=max(Max,s.a[s.top]*s.b[s.top]);
s.a[s.top]=a[i];
s.b[s.top]++;
break;
}
Max=max(Max,s.a[s.top]*s.b[s.top]);
if(s.a[s.top-1]>=a[i]){
s.b[s.top-1]+=s.b[s.top];
s.top--;
Max=max(Max,s.a[s.top]*s.b[s.top]);
} else {
s.a[s.top]=a[i];
s.b[s.top]++;
break;
}
}
}
}
for(i=0;i<=s.top;i++){
Max=max(Max,s.a[i]*n);
n-=s.b[i];
}
printf("%lld\n",Max);
}