题目大意

给出一个柱形图中柱子的高度,每个柱子的宽度为1,柱子相邻。求出柱形图中可能形成的矩形的最大面积。

题目分析

以每个柱子(高度为h[i])为中心,向两边延展求出以该h[i]为高度的矩形的最大宽度w[i]。h[i]*w[i]得到以该柱子为中心的最大矩形面积,遍历一遍之后取最大值即可。 
    关键在于求出以柱子i为中心的两边延展的矩形最大宽度。先考虑柱子i延伸到左边的最大距离:坐标p不断左移,直到h[p] < h[i],然后i - p即为柱子向左延伸的最大长度。如果直接这么做,复杂度为O(n^2)。显然,如果h[i] > h[i-1],则left_width[i] 必定为 left_width[i-1] +1, 若查找完left_width[i-1],则可以通过这个性质直接知道left_width[i]。显然,直接查找存在重复。 
    观察发现,对于当前点i和它之前的距离它最近的满足h[k] < h[i]的点k,若要获得i向左延伸的最大距离,只需要知道k,而k和i中间的那些点j不需要被查询(是否满足h[i] >= h[j])。于是,我们只保存k和i这样的点,以便在查找的时候跳过k和i中间的那些点,于是可以使用单调栈来实现。 
    单调栈中存放元素(点的索引,点的高度),若当前点的高度大于栈顶元素点的高度,则入栈;否则,弹栈,直到当前点的高度大于栈顶元素的高度,然后入栈。此时,当前点i的left_width[i] = i - 入栈之前的栈顶元素的索引。 
    同理,利用单调栈查找向右延伸的最大长度。

    感觉:单调栈/单调队列经常用在需要从某个点i向回查找,且直接查找会出现冗余访问导致复杂度为O(n^2)的问题上。在查找的时候考虑不进行往回找,而是利用数据的单调性质一遍查找,则可将复杂度降为O(n)

实现(c++)

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#define MAX_NUM 100005
int gStack[MAX_NUM][2];
int gHeight[MAX_NUM];
int gWidth[MAX_NUM][2];
long long int GetMax(int n){
memset(gWidth, 0, sizeof(gWidth));
int top = -1;
int i = 0;
while (i < n){
while (top >= 0 && gStack[top][1] >= gHeight[i]){
top--;
}
if (top >= 0)
gWidth[i][0] = i - gStack[top][0];
else{
gWidth[i][0] = i + 1;
}
top++;
gStack[top][0] = i;
gStack[top][1] = gHeight[i];
i++;
}
i = n - 1;
top = -1;
while(i >= 0){
while (top >= 0 && gStack[top][1] >= gHeight[i]){
top--;
}
if (top >= 0){
gWidth[i][1] = gStack[top][0] - i;
}
else{
gWidth[i][1] = n - i;
}
top++;
gStack[top][0] = i;
gStack[top][1] = gHeight[i];
i--;
}
long long int max = 0;
for (int i = 0; i < n; i++){
long long int tmp = (long long int) (gWidth[i][0] + gWidth[i][1] - 1)*gHeight[i];
max = max > tmp ? max : tmp;
}
return max;
}
int main(){
int n;
while(scanf("%d", &n)){
if (n == 0){
break;
}
for (int i = 0; i < n; i++){
scanf("%d", gHeight + i);
}
long long int max = GetMax(n);
printf("%lld\n", max);
}
return 0;
}

poj_2559 单调栈的更多相关文章

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

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

  2. BZOJ1012: [JSOI2008]最大数maxnumber [线段树 | 单调栈+二分]

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 8748  Solved: 3835[Submi ...

  3. BZOJ 4453: cys就是要拿英魂![后缀数组 ST表 单调栈类似物]

    4453: cys就是要拿英魂! Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 90  Solved: 46[Submit][Status][Discu ...

  4. BZOJ 3238: [Ahoi2013]差异 [后缀数组 单调栈]

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2326  Solved: 1054[Submit][Status ...

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

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

  6. bzoj1510: [POI2006]Kra-The Disks(单调栈)

    这道题可以O(n)解决,用二分还更慢一点 维护一个单调栈,模拟掉盘子的过程就行了 #include<stdio.h> #include<string.h> #include&l ...

  7. BZOJ1057[ZJOI2007]棋盘制作 [单调栈]

    题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳. 而我们的 ...

  8. 洛谷U4859matrix[单调栈]

    题目描述 给一个元素均为正整数的矩阵,上升矩阵的定义为矩阵中每行.每列都是严格递增的. 求给定矩阵中上升子矩阵的数量. 输入输出格式 输入格式: 第一行两个正整数n.m,表示矩阵的行数.列数. 接下来 ...

  9. POJ3250[USACO2006Nov]Bad Hair Day[单调栈]

    Bad Hair Day Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 17774   Accepted: 6000 Des ...

随机推荐

  1. unity, Root Motion

    (引自:http://tieba.baidu.com/p/4323644080) 然后详细看了下这个文档:http://docs.unity3d.com/Manual/RootMotion.html ...

  2. 玩转Linux文件描述符和重定向

    本文介绍linux中文件描述符与重定向的相关知识,文件描述符是与文件输入.输出相关联的整数,它们用来跟踪已打开的文件.有需要的朋友参考下. 原文出处:http://www.jbxue.com/arti ...

  3. android.animation(5) - PropertyValuesHolder与Keyframe(转)

    前几篇给大家讲了ValueAnimator.ObjectAnimator的知识,讲解了它们ofInt(),ofFloat(),ofObject()函数的用法.细心的同学可能会注意到,ValueAnim ...

  4. CSS3 Flex布局(伸缩布局盒模型)学习

    CSS3 Flex布局(伸缩布局盒模型)学习 转自:http://www.xifengxx.com/web-front-end/1408.html CSS2定义了四种布局:块布局.行内布局.表格布局盒 ...

  5. maven 中使用jstl 错误解决

    maven 中使用jstl表达式中出现如上错误.原因: 导入jstl 的jar包,却没有在pom文件中添加jstl相关的jar依赖项. <!--jstl表达式--> <depende ...

  6. 【转】搞清楚LzoCodec和LzopCodec

    使用LZO过程会发现它有两种压缩编码可以使用,即LzoCodec和LzopCodec,下面说说它们区别: LzoCodec比LzopCodec更快, LzopCodec为了兼容LZOP程序添加了如 b ...

  7. You-Get 视频下载工具 Python命令行下载工具

    You-Get 是一个命令行工具, 用来下载各大视频网站的视频, 是我目前知道的命令行下载工具中最好的一个, 之前使用过 youtube-dl, 但是 youtube-dl 吧, 下载好的视频是分段的 ...

  8. jquery 给表格tbody t 加事件

    jquery给所有td加事件 $('#erji_list_table').on('click','td', function(){ $('#yuan_content').slideToggle(&qu ...

  9. 解决将Ubuntu下导出的requirements.txt到Centos服务器上面出现pkg-resource的版本为0.0.0

    最直接有效的方法: 原因:

  10. js 内存泄漏

    在javascript中,我们很少去关注内存的管理.我们创建变量,使用变量,浏览器关注这些底层的细节都显得很正常. 但是当应用程序变得越来越复杂并且ajax化之后,或者用户在一个页面停留过久,我们可能 ...