Largest Rectangle in a Histogram

来源:互联网 发布:mac怎么用u盘重装系统 编辑:程序博客网 时间:2024/05/01 09:20
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, where0<=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 34 1000 1000 1000 10000
Sample Output
84000

由于计算量比较大,所以可以看出如果简单的暴力肯定GG,那么该怎么优化时间效率呢?不妨用单调栈来维护。


对于矩形的面积怎么求细心的同学一定一下子就发现了高度为3的有效面积是3*2;

所以说最大的面积就是以1为高,9为宽的矩行,答案自然为9。

那么现在我们的问题大概就转化为怎么高效的求出每个高度的有效宽度了,只要宽度求出来,只要乘以它的宽度,那么面积就出来了。

那么现在就该用到我们之前提到的单调栈来解决了。

我们先用一个结构体来存储我们需要的信息(1.矩形的高,2.当前矩形的宽度(之后会不断更新))。

一开始栈为空,此时到来的是高为2的矩形,记住每个到来的矩行的有效宽度都为1(之后会更行);

之后到来的高度,如果大于当前栈顶的高度,也入栈,不然的话就开始更新。

那么对于最大面积的求解我们可不可以转化为,每个高度*它的有效宽度呢,答案是可以的。

例如上面的例子

高度为2的有效面积是2*1;

高度为1的有效面积是1*9;

高度为4的有效面积是4*1;

高度为5的有效面积是5*1;

记住if(栈顶高度大于等于目前到来高度)POP;

你会发现目前栈顶(5,1)>(1,1)那么该怎么办呢;

先取出(5,1)然后更新Max,就是当前最大的面积和(5*宽)比哪个面积大Max = min(Max,(5*1));

然后现在栈顶为(4,2),接着更新;

栈顶为(1,4)接着更新;

栈为空(1,5)入栈。

然后接着重复就可以了。

PS.最后如果栈不为空记得计算栈内元素的面积。


代码如下:

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>#include <map>#include <stack>#include <vector>using namespace std;typedef long long LL;const int maxn = 100000+10;const int INF = 0x3f3f3f3f;struct node{    LL h,w;};int n;LL Max,H;int main(){    node temp,t;    stack<node>S;    while(~scanf("%d",&n) && n){        while(!S.empty()){            S.pop();        }        Max = 0;        for(int i = 0; i < n; i++){            scanf("%lld",&H);            temp.h = H;            temp.w = 1;            if(S.empty()){                S.push(temp);            }            else{                int w = 0;                while(!S.empty()){                    t = S.top();                    if(t.h >= temp.h){                        Max = max(Max,t.h*(t.w+w));                        w += t.w;                        S.pop();                    }                    else                        break;                }                temp.w += w;                S.push(temp);            }        }        int w = 0;        while(!S.empty()){            t = S.top();            Max = max(Max,t.h*(t.w+w));            w += t.w;            S.pop();        }        printf("%lld\n",Max);    }    return 0;}


0 0
原创粉丝点击