[POJ2559&POJ3494] Largest Rectangle in a Histogram&Largest Submatrix of All 1’s 「单调栈」
Largest Rectangle in a Histogram
http://poj.org/problem?id=2559
题意:给出若干宽度相同的矩形的高度(条形统计图),求最大子矩形面积
解题思路
单调栈的经典题(嫌弃字多可以先看后面的示例再来看这个思路)
显然,最终的子矩形高度一定和某一个矩形相等(反证)。因此一个暴力的做法就是枚举每一个矩形,然后往两边扩散。在它左侧找到第一个高度比它小的,右侧也一样。则可以求出最大可扩散宽度,乘上高度即可以更新答案。复杂度O(n2)
如果说要优化刚才的算法,也就可以优化寻找最大可扩散宽度的速度
让每一个矩形依次入栈,保存两个关键字:矩形高度,其最大左扩散宽度。保证栈内的矩形高度单调递增
我们可以得到结论:目前栈内的一个矩形uu,在原图中从uu开始一直到栈顶所在的矩形,高度一定都比uu高。这就是为什么我们不需要统计栈内矩形的最大右扩散宽度,因为最大右扩散宽度就是栈顶
再回忆一下最大左扩散宽度的意义,是在它左侧的高度大于它的矩形们。这让我们又得出一个结论:目前栈内的一个矩形uu,如果它的最大左扩散宽度大于11,则这些它所能扩散到的矩形一定都不在栈中。这也很容易发现,因为栈是单调递增的。或者,我们可以得到一个更形象的结论:栈内连续的两个矩形u,vu,v,如果在原图中他们之间有矩形,那么这些矩形一定都高于u,vu,v
因此刚才我们所说的最大左扩散宽度,其实等同于在原图中,它到栈中上一个矩形之间相隔了多少矩形
当一个新的矩形进来的时候,它会弹走若干个矩形。而栈内一个矩形实际上代表着原图中一段矩形。因此可以说是弹走了几段矩形。但是这些被弹走的矩形只不过出栈,在原图中并不会消失。因此他们所代表的的宽度不应当消失,所以我们将他们累积在新进来的这个矩形上。这也非常符合事实——这个新的矩形之所以能弹走这若干个矩形是因为自己比他们矮,因此都可以扩散到。换句话说,被弹走的这一系列矩形最多只能向右扩散到这个新矩形,因此留着它们就没有意义了
而对于任何一个要出栈的矩形,我们需要统计由它的高度所能扩散出去的最大子矩形面积。由于它的最大左扩散宽度已知,唯一需要知道的就是它的最大右扩散宽度。那么由于它在栈里,它的最大右扩散宽度也就是从它一直到最早先的栈顶之间的宽度。因此我们只需要在弹栈的过程中一路累积每个出栈矩形的最大左扩散宽度,加起来就是这一段宽度了。
另外,如果处理完了最后一个矩形以后栈依然有剩余,则应当弹完并更新答案
保证了每个矩形入栈以及出栈恰好一次,在正确性显然的条件下,复杂度O(n)
这里给出示例,以帮助理解:
例子就用题目中的[2,1,5,6,2,3]吧
首先,如果栈是空的,那么索引i入栈。那么第一个i=0就进去吧。注意栈内保存的是索引,不是高度。然后i++。
然后继续,当i=1的时候,发现h[i]小于了栈内的元素,于是出栈。(由此可以想到,哦,看来stack里面只存放单调递增的索引)
这时候stack为空,所以面积的计算是h[t] * i.t是刚刚弹出的stack顶元素。也就是蓝色部分的面积。
继续。这时候stack为空了,继续入栈。注意到只要是连续递增的序列,我们都要keep pushing,直到我们遇到了i=4,h[i]=2小于了栈顶的元素。
这时候开始计算矩形面积。首先弹出栈顶元素,t=3。即下图绿色部分。
接下来注意到栈顶的(索引指向的)元素还是大于当前i指向的元素,于是出栈,并继续计算面积,桃红色部分。
最后,栈顶的(索引指向的)元素大于了当前i指向的元素,循环继续,入栈并推动i前进。直到我们再次遇到下降的元素,也就是我们最后人为添加的dummy元素0.
同理,我们计算栈内的面积。由于当前i是最小元素,所以所有的栈内元素都要被弹出并参与面积计算。
注意我们在计算面积的时候已经更新过了maxArea。
Code
这里如果一下子理解不过来的话,wid可以分两步求,wid = l + r
r = j-t; //右边能扩散的最大宽度
l = s.empty()?t:(t-s.top()-); //左边能扩大的最大宽度
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
using namespace std; typedef long long ll;
ll h[]; stack<int> s; int main()
{
int n;
while (scanf("%d", &n)&&n) {
memset(h, , sizeof(h));
while(!s.empty()) s.pop();
for (int i = ; i < n; i++)
scanf("%lld", &h[i]); ll j = , res = ;
while (j<=n) {
if (s.empty()||h[s.top()]<=h[j])
s.push(j++);
else {
ll t = s.top(); s.pop();
ll wid = s.empty()?j:(j-s.top()-);
res = max(res, h[t]*wid);
}
}
printf("%lld\n", res);
}
}
这题算法是没什么问题的,但是特别要注意的是,如何不单独写成一个函数的话,由于最后push进去了h值为0的n,这个对之后wid求值时候可能为负数就会出现问题,还有就是要保证每组数据输入完后h[n]要为0
Largest Submatrix of All 1’s
http://poj.org/problem?id=3494
题意:给你一个n*m的矩阵,矩阵的每个位置值为0或者1,问你在这个矩阵中全部由1组成的最大的矩形面积为多少。
思路:很巧妙的方法。把图拆成一行行来做,分别求以每行为底的最大矩形面积
矩阵中的子矩阵等同于序列中的子序列,只不过此题要做一个预处理,将这个矩阵分为以每一行为x轴
的n
个柱状图,对于每一个等于1
的点,它的高度都等于上一行同一列的点的高度加一。
初始化后,再对n
个柱状图进行如上题POJ2559
的处理。
例如:





#include<stdio.h>
#include<stack>
using namespace std; int h[][];
stack<int> s; int main()
{
int n, m;
while(~scanf("%d%d",&n,&m)) {
for(int i = ; i < n; i++) {
for(int j = ; j < m; j++) {
scanf("%d",&h[i][j]);
if(h[i][j]==&&i>) h[i][j]+=h[i-][j];
}
}
for(int i = ; i < n; i++) h[i][m] = ; int res = ;
for (int i = ; i < n; i++) {
while(!s.empty()) s.pop();
int j = ;
while (j<=m) {
if (s.empty()||h[i][s.top()]<=h[i][j])
s.push(j++);
else {
int t = s.top(); s.pop();
int wid = s.empty()?j:(j-s.top()-);
res = max(res, h[i][t]*wid);
}
}
} printf("%d\n", res);
}
return ;
}
参考自以下博客:
https://www.cnblogs.com/qixingzhi/p/9497208.html
https://www.cnblogs.com/lichen782/p/leetcode_Largest_Rectangle_in_Histogram.html
https://www.cnblogs.com/boring09/p/4231906.html
[POJ2559&POJ3494] Largest Rectangle in a Histogram&Largest Submatrix of All 1’s 「单调栈」的更多相关文章
- ☆ [POJ2559] Largest Rectangle in a Histogram 「单调栈」
类型:单调栈 传送门:>Here< 题意:给出若干宽度相同的矩形的高度(条形统计图),求最大子矩形面积 解题思路 单调栈的经典题 显然,最终的子矩形高度一定和某一个矩形相等(反证).因此一 ...
- POJ2559 Largest Rectangle in a Histogram —— 单调栈
题目链接:http://poj.org/problem?id=2559 Largest Rectangle in a Histogram Time Limit: 1000MS Memory Lim ...
- 【题解】Largest Rectangle in a Histogram [SP1805] [POJ2559]
[题解]Largest Rectangle in a Histogram [SP1805] [POJ2559] [题目描述] 传送: \(Largest\) \(Rectangle\) \(in\) ...
- poj2559 Largest Rectangle in a Histogram(单调栈)
Description A histogram is a polygon composed of a sequence of rectangles aligned at a common base l ...
- POJ2559 Largest Rectangle in a Histogram (单调栈
Largest Rectangle in a Histogram Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 26012 ...
- NYOJ-258/POJ-2559/HDU-1506 Largest Rectangle in a Histogram,最大长方形,dp或者单调队列!
Largest Rectangle in a Histogram 这么经典的题硬是等今天碰到了原题现场懵逼两小时才会去补题.. ...
- poj 2559 Largest Rectangle in a Histogram - 单调栈
Largest Rectangle in a Histogram Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 19782 ...
- DP专题训练之HDU 1506 Largest Rectangle in a Histogram
Description A histogram is a polygon composed of a sequence of rectangles aligned at a common base l ...
- Largest Rectangle in a Histogram(DP)
Largest Rectangle in a Histogram Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/32768K ...
随机推荐
- java写出PDF
1\包 <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</ar ...
- CI框架使用(一)
CI框架的使用是很简单,也 是mvc模式.其中有好多类直接调用. 在使用帮助函数的时候,都需要手动加载,或者是在配置文件中加一个自动加载 $this->load->helper('ur ...
- c# 自己实现可迭代的容器
在c#中我们经常使用到foreach语句来遍历容器,如数组,List,为什么使用foreach语句能够遍历一个这些容器呢,首先的一个前提是这些容器都实现了IEnumerable接口,通过IEnumer ...
- iOS开发系列之性能优化(上)
本篇主要记录一下我对界面优化上的一些探索.关于时间优化的探索将会在中篇里进行介绍.下篇将主要介绍一些耗电优化.安装包瘦身的探索. ### 1.卡顿原理 要了解卡顿原理,需要对帧缓冲区.垂直同步.CPU ...
- ASP.NET Core on K8S学习初探(2)K8S基本概念快速一览
在上一篇<单节点环境搭建>中,通过Docker for Windows在Windows开发机中搭建了一个单节点的K8S环境,接下来就是动人心弦的部署ASP.NET Core API到K8S ...
- 如何使用共享网卡的NAT模式配置VMware12中的CentOS6.7的上网功能
1.首先共享网卡的NAT模式是通过win10中的VMnet8来通信的,如下双击VMnet8 2.点击[详细信息]查看VMnet8的IPV4地址为192.168.232.110,掩码为255.255.2 ...
- centos7安装apache http server启动失败--Failed to start The Apache HTTP Server.
centos7安装apache http server启动失败 除了nginx可以开启http服务外,apche http server也可以开启http服务,安装过程如下:1. 首先,检测是 ...
- java的封神之路[转载]
一.基础篇 1.1 JVM 1.1.1. Java内存模型,Java内存管理,Java堆和栈,垃圾回收 http://www.jcp.org/en/jsr/detail?id=133 http://i ...
- 基于SpringBoot的Web API快速开发基础框架
其实还是很因为懒,才会有这个案例项目的产生,每次开启一个终端的小服务都要整理一次框架,造成重复的.不必要的.缺乏创造性的劳动,SO,本着可以用.用着简单的原则上传代码到Github,希望有需要的朋友直 ...
- C语言的指针移动怎么理解
C Primer pkus(第五版)中文版,老外写的还是很经典的,推荐给朋友们,购买地址:C primer plus 5版中文版购买 另外再推荐本书: 程序员面试宝典(第5版)第五版:程序员面试宝典( ...