hdu1506 直方图中最大的矩形 单调栈入门
hdu1506 直方图中最大的矩形 单调栈入门
直方图是由在公共基线对齐的矩形序列组成的多边形。矩形具有相同的宽度,但可能具有不同的高度。例如,左侧的数字显示了由高度为2,1,4,5,1,3,3的矩形组成的直方图,单位为1,其中矩形的宽度为1:
通常,直方图用于表示离散分布,例如文本中字符的频率。请注意,矩形的顺序,即它们的高度很重要。计算在公共基线上对齐的直方图中最大矩形的面积。右图显示了所描述的直方图的最大对齐矩形。
输入包含几个测试用例。每个测试用例都描述一个直方图,并以整数n开头,表示它组成的矩形的数量。您可以假设1 <= n <= 100000。然后遵循n个整数h1,...,hn,其中0 <= hi <= 1000000000。这些数字表示直方图的矩形的高度,从左到右订购。每个矩形的宽度是1.零跟在最后一个测试用例的输入之后。对于每个测试用例,在一行中输出指定直方图中最大矩形的面积。请记住,这个矩形必须在公共基线上对齐。
单调栈,就是具有单调性质的栈,用途与单调队列有相似之处。我们先来分析一下这道题。一个最大矩阵的高度,就是矩阵覆盖到的,高度最小的条形的高度。所以我们只需要枚举每个条形作为高度最小的条形,所能形成的最大矩阵,然后取最大值即可。
那么现在,问题就转换成了对于每个条形,以它的高度作为矩阵的高度,矩阵最多能向左和向右延伸到的高度,相当于求这个矩阵,左边有连续多少个矩阵比它高,右边有连续多少个矩阵比它高。所以,长度就是:(右边第一个比它小的条形的位置-左边第一个比它小的条形的位置-1)。如何求第一个比当前数小的左侧或右侧数呢?这就要用到单调栈。
设第一个比当前数(序号为i)小的左侧数为\(left[i]\)。算法的流程是这样的:设现在程序循环到第i个数,如果当前,栈顶的数大于等于第i个数,说明什么?说明序号i以后的数j,它们的\(left[j]\)一定不会是栈顶那个数,因为选了j一定能选i。既然这样,直接把j从栈中弹出,然后继续判断……直至第i个数遇到比它小的栈顶的数。这个数就是\(left[i]\),因为比i小的数只会被更小更优的数替换。然后,将i入栈。这样就把那些无用的,值大于第i个数,却在第i个数左边的数统统用第i个数替换了。这就去除了冗余状态。
从这道题,我们能发现一些单调栈和单调队列的共同点和不同点。共同点:1.它们都保持了单调性。2.它们都通过一个元素必定比其它优,就可以直接删去其他元素的方法,去除了冗余状态。3.由于元素都是一进一出,时间复杂度为O(n)。不同点:单调队列,最优值和插入操作在队首,在弹出操作在队尾。单调栈,最优值,插入操作和弹出操作都在栈顶。
#include <cstdio>
using namespace std;
const int maxn=1e5+5;
typedef long long LL;
struct stack{
int t, a[maxn];
void reset(){ t=0; }
void pop(){ if (--t==-1) ++t; }
void add(int x){ a[++t]=x; }
int top(){ return a[t]; }
}s;
int n;
int a[maxn], lessleft[maxn], lessright[maxn];
int max(const int &a, const int &b){ return a<b?b:a; }
LL max(const LL &a, const LL &b){ return a<b?b:a; }
int main(){
while (scanf("%d", &n), n){
a[0]=a[n+1]=-1;
s.reset(); s.add(0);
for (int i=1; i<=n; ++i){
scanf("%d", &a[i]);
while (a[i]<=a[s.top()]) s.pop();
lessleft[i]=s.top(); s.add(i);
}
s.reset(); s.add(n+1);
for (int i=n; i>=1; --i){
while (a[i]<=a[s.top()]) s.pop();
lessright[i]=s.top(); s.add(i);
}
LL maximum=0;
for (int i=1; i<=n; ++i)
maximum=max(maximum,
LL(lessright[i]-lessleft[i]-1)*a[i]);
printf("%lld\n", maximum);
}
return 0;
}
hdu1506 直方图中最大的矩形 单调栈入门的更多相关文章
- [LeetCode] Largest Rectangle in Histogram 直方图中最大的矩形
Given n non-negative integers representing the histogram's bar height where the width of each bar is ...
- [LeetCode] 84. Largest Rectangle in Histogram 直方图中最大的矩形
Given n non-negative integers representing the histogram's bar height where the width of each bar is ...
- POJ 3250 Bad Hair Day【单调栈入门】
Bad Hair Day Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 24112 Accepted: 8208 Des ...
- AcWing:131. 直方图中最大的矩形(贪心 + 单调栈)
直方图是由在公共基线处对齐的一系列矩形组成的多边形. 矩形具有相等的宽度,但可以具有不同的高度. 例如,图例左侧显示了由高度为2,1,4,5,1,3,3的矩形组成的直方图,矩形的宽度都为1: 通常,直 ...
- [leetcode]84. Largest Rectangle in Histogram直方图中的最大矩形
Given n non-negative integers representing the histogram's bar height where the width of each bar is ...
- 51nod 1102 面积最大的矩形 (单调栈)
链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1102 思路: 首先介绍下单调栈的功能:利用单调栈,可以找到从左/ ...
- [51nod1102]面积最大的矩形(单调栈||预处理)
题意:求序列上某区间最小值乘区间长度的最大值. 解题关键:很早就在<挑战程序设计竞赛>中见过了,单调栈模板题,注意弹栈时如何处理后面的元素. 法一:单调栈 #include<bits ...
- Leetcode84. 柱状图中最大的矩形(单调栈)
84. 柱状图中最大的矩形 前置 单调栈 做法 连续区间组成的矩形,是看最短的那一块,求出每一块左边第一个小于其高度的位置,右边也同理,此块作为最短限制.需要两次单调栈 单调栈维护递增区间,每次不满足 ...
- BZOJ1113 海报PLA1(单调栈入门题)
一,自己思考下 1,先自己思考下 N个矩形,排成一排,现在希望用尽量少的海报去cover住它们. 2,不懂. 着实不懂. 3,分析下,最优性问题对吧,然后就每什么想法了.. 虽然肯定和单调栈和单调队列 ...
随机推荐
- Wannafly挑战赛12 A 银行存款 【DP】【DFS】
链接:https://www.nowcoder.com/acm/contest/79/A 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536 ...
- PAT天梯赛 L2-002. 链表去重 【STL】
题目链接 https://www.patest.cn/contests/gplt/L2-002 思路 用结构体 存储 一个结点的地址 值 和下一个地址 然后从首地址开始 往下走 并且每个值的绝对值 都 ...
- iOS 分享功能开发
iOS 开发过程中可能会遇到需要进行第三方分享的需求,比如向QQ,微信,微博等分享 如下图 我们今天要讲到的方式是使用了一个第三方工具: http://www.sharesdk.cn 一,注册账号 去 ...
- 使用log4j将不同级别的日志信息输出到不同的文件中
使用log4j.xml xml格式的配置文件可以使用filter. 例如想只把log4j的debug信息输出到debug.log.error信息输出到error.log,info信息输出到info.l ...
- Ubuntu 17.4下如何安装和配置flash player
Ubuntu Linux系统下没有自带的flash player,要自己手动安装.下面post出简单的安装过程. 首先打开终端,输入命令:sudo apt-get install flashplugi ...
- 京东面试题 Java相关
1.JVM的内存结构和管理机制: JVM实例:一个独立运行的java程序,是进程级别 JVM执行引擎:用户运行程序的线程,是JVM实例的一部分 JVM实例的诞生 当启动一个java程序时.一个JVM实 ...
- 分享知识-快乐自己:oracle表分区详解
从以下几个方面来整理关于分区表的概念及操作: 1)表空间及分区表的概念: 2)表分区的具体作用: 3)表分区的优缺点: 4)表分区的几种类型及操作方法: 5)对表分区的维护性操作: 1):表空间及分区 ...
- [原创]Java动态生成word文档(图文并茂)
很多情况下,软件开发者需要从数据库读取数据,然后将数据动态填充到手工预先准备好的Word模板文档里,这对于大批量生成拥有相同格式排版的正式文件非常有用,这个功能应用PageOffice的基本动态填充功 ...
- Oracle学习笔记_05_ 一个创建表空间、创建用户、授权的完整过程
一.完整命令 su - oracle sqlplus /nolog conn /as sysdba create tablespace scaninvoice logging datafile '/u ...
- linux命令学习笔记(44):top命令
top命令是Linux下常用的性能分析工具,能够实时显示系统中各个进程的资源占用状况,类似于Windows的任务管 理器.下面详细介绍它的使用方法.top是一个动态显示过程,即可以通过用户按键来不断刷 ...
