http://poj.org/problem?id=2559

Largest Rectangle in a Histogram
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 12297   Accepted: 3974

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 integersh1,...,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 思路: 题解部分转自:http://blog.csdn.net/hopeztm/article/details/7868581

题目大意:

给出一个柱形统计图(histogram), 它的每个项目的宽度是1, 高度和具体问题有关。 现在编程求出在这个柱形图中的最大面积的长方形。

例如:

7 2 1 4 5 1 3 3

7表示柱形图有7个数据,分别是 2 1 4 5 1 3 3, 对应的柱形图如下,最后求出来的面积最大的图如右图所示。

分析:

如果采用枚举的方式,如果当前我们枚举项是 i = 0, 即 height = 2,

我们用另外两个变量 j 和k 向左和向右两个方向搜素,找到第一个 小于 height的下标,这样我们就找到了用 i 项作为高度长方形了。

我们假设 -1位置,和最右高度都是无穷小。

例如:

i = 0, j = -1, k = 1, 最后的面积是 (k - j - 1) * height = 2

i = 1, j = -1, k = 7, 最后面积是( k - j - 1) * height = 7;

...

i = 3, j = 2, k = 5 面积是 ( k - j - 1) * height = 8

枚举出所有的长方形的同时,然后得到最后的面积。

不过这样的程序的时间复杂度是 O(n^2)

我们如何能仅仅做一次,就求出这个面积呢?

观察:

当我们扫扫描到第一个高度 H1 = 2的时候,我可以标记它的起始位置1, 因为我们还不知道它将向右扩展到什么地方,所以继续扫面。

当遇到第二项 H2 = 1, 因为这项比之前的小,我们知道,用H1做高度的长方形结束了,算出它的面积。

同时这个时候,我们多了一个高度H2,用它做长方形高度的长方形起始位置应该是在哪里呢? 因为H1的高度比H2要高,所以这个起始位置自然是H1所在的位置。

为了模拟上面的过程,我们引入单调栈~

我们先定义我们我们要保存的每一项数据

struct Node

{

int height;

int startPosition;

};

用来描述某一个高度,和这个高度的起始位置。

然后我们按照高度来组织成单调栈。我们来看一下它是如何工作的。

为了不用考虑堆栈为空的情况,我们用插入栈底 一个高度(0, 0)的项。

数据:

 2 1 4 5 1 3 3

这样初始化

(0 , 0)

I = 1

当扫描到(2, 1)时候,因为高度2 大于栈顶,插入

(0, 0),  (2, 1)

I = 2: 

当扫描到1的时候,因为1小于栈顶高度2, 我们认为栈顶的那个高度应不能再向右扩展了,所以我们将它弹出

这个时候扫描到 i = 2;

高度是 (i - 1(H1.startIndex)) * H1.height = 2;

我们得到一个面积是2的长方形。

同时我们发现高度是1的当前高度,可以扩展到 H1所在的下标,所以我们插入( 1, 1) 堆栈变成

(0, 0), (1, 1) 因为(2, 1)已经不能向右伸展了,已经被弹出了

i = 3

(0, 0), (1, 1), ( 4 3)

i = 4

(0, 0), (1, 1), (4, 3), (5, 4)

i = 5 

这个时候当前高度小于栈顶高度,我们认为栈顶已经不能向右扩展,所以弹出,并且获得面积 ( i  - H5.startindex) * H5.height = (5 - 4 ) * 5 = 5

弹出这个元素后,其实(4, 3)的高度也要比 1 大,所以把这个也弹出来,同样方式获得面积 8.

最后我们的堆栈是

(0, 0) , (1, 1)

i  = 6

(0, 0), (1, 1), ( 3, 6)

i = 7

(0, 0), (1, 1), (3, 6)

i = 8

最后一步是有点特殊的,因为我们必须要把所有的元素都弹出来,因为栈里面的高度,都坚持到了最后,我们要把这些高度组成的长方形拿出来检测。

我们可以假设扫面到8的时候,高度是0,(最小值)

弹出(3,6)获得面积 (8 - 6 ) * 3 = 6

弹出(1, 1)获得面积(8 - 1) * 1 = 7

最后的面积是8.

注意:注意取值范围,需要用到64位的int

代码:

 #include <iostream>
#include <stdio.h>
#include<stack> using namespace std; struct Nod
{
__int64 height;
__int64 startPos;
}node; stack<Nod> stk; int main()
{
__int64 n,a;
while(~scanf("%I64d",&n)&&n)
{
__int64 i,maks=;
while(!stk.empty()) stk.pop();
node.height=;
node.startPos=;
stk.push(node);
for(i=;i<n;i++)
{
scanf("%I64d",&a);
node.startPos = i; //先记录当前位置,如果栈中的节点height值比a大,则弹出并更新node.startPos
while(a<stk.top().height) //注意这里不能用 a<node.height
{
node = stk.top(); //记录stk.top()顺便更新node.startPos的值,直到记录最后弹出的节点的startPos值
stk.pop();
__int64 temp = node.height * (i - node.startPos);
if(maks<temp) maks = temp; }
node.height = a;
stk.push(node); //压入栈,这里node.startPos的值视情况会有所改变的
}
//对于栈中还剩余的其他元素进行弹出处理
while(!stk.empty())
{
__int64 temp = stk.top().height * (n - stk.top().startPos);
if(maks<temp) maks = temp;
stk.pop();
}
printf("%I64d\n",maks);
}
return ;
}

题解部分转自:http://blog.csdn.net/hopeztm/article/details/7868581

poj 2559 Largest Rectangle in a Histogram (单调栈)的更多相关文章

  1. poj 2559 Largest Rectangle in a Histogram - 单调栈

    Largest Rectangle in a Histogram Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 19782 ...

  2. POJ 2559 Largest Rectangle in a Histogram(单调栈)

    传送门 Description A histogram is a polygon composed of a sequence of rectangles aligned at a common ba ...

  3. POJ 2559 Largest Rectangle in a Histogram (单调栈或者dp)

    Largest Rectangle in a Histogram Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 15831 ...

  4. PKU 2559 Largest Rectangle in a Histogram(单调栈)

    题目大意:原题链接 一排紧密相连的矩形,求能构成的最大矩形面积. 为了防止栈为空,所以提前加入元素(-1,0) #include<cstdio> #include<stack> ...

  5. [POJ 2559]Largest Rectangle in a Histogram 题解(单调栈)

    [POJ 2559]Largest Rectangle in a Histogram Description A histogram is a polygon composed of a sequen ...

  6. stack(数组模拟) POJ 2559 Largest Rectangle in a Histogram

    题目传送门 /* 题意:宽度为1,高度不等,求最大矩形面积 stack(数组模拟):对于每个a[i]有L[i],R[i]坐标位置 表示a[L[i]] < a[i] < a[R[i]] 的极 ...

  7. poj 2559 Largest Rectangle in a Histogram 栈

    // poj 2559 Largest Rectangle in a Histogram 栈 // // n个矩形排在一块,不同的高度,让你求最大的矩形的面积(矩形紧挨在一起) // // 这道题用的 ...

  8. POJ2559 Largest Rectangle in a Histogram —— 单调栈

    题目链接:http://poj.org/problem?id=2559 Largest Rectangle in a Histogram Time Limit: 1000MS   Memory Lim ...

  9. 题解报告:poj 2559 Largest Rectangle in a Histogram(单调栈)

    Description A histogram is a polygon composed of a sequence of rectangles aligned at a common base l ...

随机推荐

  1. AT-Activity

    关于Activity的粗略翻译 原地址:Activity  类概述: Activity是独立的.突出的可被用户操作的东西.几乎所有的Activity都是与用户进行交互的,所以这些Activity会很小 ...

  2. 利用JS_SDK实现QQ第三方登录

    前言 现如今,第三方登录已成为大部分网站必备的一项基础技能,引入时髦的第三方登录不仅能帮你吸引更多的用户,也让你的网站可以充分利用其他大型网站的用户资源.本次教程将让你的网站最快捷便利地引入QQ登录. ...

  3. [转]windows下安装Object-C开发环境

    本文转自:http://hi.baidu.com/jeremylai/item/f40b9116cb3c5d582b3e22f5 在Windows下搭建Objective C开发环境,需要到GNUst ...

  4. Redhat和ubuntu的区别

    风大神给了我一个完全基于 Linux 的操作系统ubuntu(乌班图)(是一个以桌面应用为主的Linux操作系统),当然作为linux,服务器应用都不会弱.,说是这个好用,可飞凌上资料用的居然是red ...

  5. #291 div.2

    A.水题 数字翻转,将每一位大于等于5的数字t翻转成9-t,注意不要有前导0,且翻转后数字的位数不变(即9999->9000...刚开始以为应该翻转成0了= =) #include<ios ...

  6. vim纯文本处理插件txtbrowser

    纯文本处理插件:txtBrowser 插件作者:http://guoyoooping.blog.163.com/ Github地址:https://github.com/vim-scripts/Txt ...

  7. jQuery mouseover与mouseenter,mouseout与mouseleave的区别

    mouseover与mouseenter 不论鼠标指针穿过被选元素或其子元素,都会触发 mouseover 事件. 只有在鼠标指针穿过被选元素时,才会触发 mouseenter 事件. mouseou ...

  8. Hadoop基于Protocol Buffer的RPC实现代码分析-Server端

    http://yanbohappy.sinaapp.com/?p=110 最新版本的Hadoop代码中已经默认了Protocol buffer(以下简称PB,http://code.google.co ...

  9. ~/.ssh目录找不到解决方法

    执行 cd ~/.ssh发现ssh目录找不到 [root@ocdp2 ~]# cd ~/.ssh -bash: cd: /root/.ssh: No such file or directory 原因 ...

  10. 支持IE,FireFox,Chrome三大主流浏览器,通过js+Flash方式将table导出Excel文件

    今天在做项目的时候,遇到了前端下载Excel的功能,结果原先的代码,如下: function generate_excel(tableid) {        var table = document ...