Largest Rectangle in a Histogram

来源:互联网 发布:8080端口如何开启 编辑:程序博客网 时间:2024/05/22 01:36

Problem 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 <i>n</i>, denoting the number of rectangles it is composed of. You may assume that <i>1<=n<=100000</i>. Then follow <i>n</i> integers <i>h<sub>1</sub>,...,h<sub>n</sub></i>, where <i>0<=h<sub>i</sub><=1000000000</i>. These numbers denote the heights of the rectangles of the histogram in left-to-right order. The width of each rectangle is <i>1</i>. 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

      题意:让求最大矩形的面积。先搞清楚什么样子的才叫矩形,并不是说一定要等高度,而是可以截出来的,如上面图。

      这个思路应该是对于每一个点,都截一次,也就是以这个点的高为准,向左找找找,找到第一个比他矮的点停下;向右找找找,找到比他矮的点停下。面积,面积怎么算,木桶原理听说过吧,木桶能装多少水取决于最短的那块木板的高度。这个面积一样,用你当前基准点也就是最短的点乘以长度。这样以每个点都找一遍,找到最大值就ok了。

      以每个点向左向右找的过程,可以用双重循环,肯定是超时。可以用单调栈来找,也可以用并查集思想来找。

      当然每个点都要往左找一遍往右找一遍,要找上两次的。

      这道题真是神奇的一道题,用这个题复制下来改一改,解决掉了好几道题了,简直不要太高兴。

      这几个衍生的题如下:

Largest Submatrix of All 1’s    点击打开链接

Terrible Sets    点击打开链接

Feel Good    点击打开链接


代码如下:

#if 0                          // 普通寻找 并查集思想      对的   输入出long long 用%lld不对   用的%I64d#include<iostream>#include<stdio.h>using namespace std;int main(){long long int a[100010];int l[100010];int r[100010];int N;while(~scanf("%d",&N) && N){for(int i=1;i<=N;i++){scanf("%I64d",&a[i]);}for(int i=1;i<=N;i++){int pos=i;while(pos>1 && a[i]<=a[pos-1])pos=l[pos-1];l[i]=pos;}for(int i=N;i>=1;i--){int pos=i;while(pos<N && a[i]<=a[pos+1])pos=r[pos+1];r[i]=pos;}long long maxn=0;long long area=0;for(int i=1;i<=N;i++){area=a[i]*(r[i]-l[i]+1);if(maxn<area)maxn=area;}printf("%I64d\n",maxn);//printf("%lld\n",maxn);}return 0;}#endif // 1#if 0                       //单调栈  对了#include<iostream>#include<stdio.h>using namespace std;int main(){long long int a[100010];int l[100010];int r[100010];int s[100010];int N;int top;while(cin>>N && N){        for(int i=1;i<=N;i++){scanf("%I64d",&a[i]);l[i]=i;r[i]=i;}top=0;for(int i=1;i<=N;i++)   //向左找{while(top && a[i]<=a[s[top]])                top--;            if(top==0)                l[i]=1;            else                l[i]=s[top]+1;//s[top]存的数的值肯定是比a[i]小的,所以地s[top]+1个位置即为所求            s[++top]=i;}top=0;for(int i=N;i>=1;i--){while(top && a[i]<=a[s[top]])                top--;            if(top==0)                r[i]=N;            else                r[i]=s[top]-1;            s[++top]=i;}long long int maxn=0;long long int area;for(int i=1;i<=N;i++){area=a[i]*(r[i]-l[i]+1);if(maxn<area)maxn=area;}printf("%I64d\n",maxn);}return 0;}#endif // 1



原创粉丝点击