【AcWing】蓝桥杯集训每日一题Day17|单调队列|求直方图中最大矩形|单调栈|模型转化|1413.矩形牛棚(C++)

1413.矩形牛棚
1413. 矩形牛棚 - AcWing题库
难度:中等
时/空限制:1s / 256MB
总通过数:1914
总尝试数:3823
来源:

usaco training 6.1
算法标签

单调栈

题目内容

作为一个资本家,农夫约翰希望通过购买更多的奶牛来扩大他的牛奶业务。
因此,他需要找地方建立一个新的牛棚。
约翰购买了一大块土地,这个土地可以看作是一个 R 行(编号 1∼R)C 列(编号 1∼C)的方格矩阵。
不幸的是,他发现其中的部分方格区域已经被破坏了,因此他无法在整个 R×C 的土地上建立牛棚。
经调查,他发现共有 P 个方格内的土地遭到了破坏。
建立的牛棚必须是矩形的,并且内部不能包含被破坏的土地。
请你帮约翰计算,他能建造的最大的牛棚的面积是多少。

输入格式

第一行包含三个整数 R,C,P。
接下来 P 行,每行包含两个整数 r,c,表示第 r 行第 c 列的方格区域内土地是被破坏的。

输出格式

输出牛棚的最大可能面积。

数据范围

1≤R,C≤3000,
0≤P≤30000,
1≤r≤R,
1≤c≤C

输入样例:
3 4 2
1 3
2 1
输出样例:
6
题目解析

行数和列数都是在3000,整个矩阵的大小就是3000的平方,将近1000万的数据量
需要将时间复杂度控制在 O ( n m ) O(nm) O(nm),跟整个矩阵的方格数呈线性关系

枚举

枚举左右边界,再把上下边界枚举出来,再判断中间的格子是不是都没有被破坏
左右边界,n2,上下边界n2,中间的格子数量n^2,时间复杂度是 O ( n 6 ) O(n^6) O(n6)

优化

求中间格子里有没有坏方块,可以用二维前缀和,就不需要枚举了,直接算一下中间的总和是不是0就可以了
如果被破坏的话,就是1;没被破坏,就是0
用二维前缀和可以优化掉一个n^2

考虑能不能枚举少一些的边

可以先用 O ( n ) O(n) O(n)枚举下边界,下边界确定之后,可以预处理一下,每一列都可以求一下往上最多有多少块没有被连续破坏的方块
这样就可以得到一个直方图,求这个直方图中的最大矩形
可以用单调栈,做到 O ( n ) O(n) O(n)的计算量
总共就是 O ( n 2 ) O(n^2) O(n2)

单调栈

O ( n ) O(n) O(n)的时间预处理出来每个数左边第一个比它小的数,以及每个数右边第一个比它小的数

为什么可以用单调栈求解

在此基础上枚举一下上边界,矩形的上边界一定会取直方图的上面的一条边,可以依次枚举一下到底取哪一个小长条的上面的边
当枚举到其中一条边时,上下边界就确定了,接下来考虑左右边界,左边如果能延伸,就一直往左边延伸,知道延伸到左边第一个比当前的高度低的方块为止,有边界也是
![[Pasted image 20240409212850.png]]

上下边界确定之后,左边边界就等于左边第一个比它矮的长条右边这条边,右边边界就是右边第一个比当前矮的长条的左边这一条边
因此只要对于每一个长条,预处理出来左边第一个比它矮的长条,和右边第一个比它矮的长条,就可以知道左右边界了,进而就可以知道矩形的宽度了
就可以知道当前的最大面积是多少

高度预处理,每一列的高度都是独立的,所以可以按列预处理,通过递推的方法

代码
#include <iostream>
#include <cstring>
#include <algorithm>using namespace std;const int N = 3010;int n, m, P;
int g[N][N], h[N][N];  
//g表示每个位置有没有被破坏,h表示每个格子往上数最多可以数多少个没有被破坏的矩形
int stk[N], top;   //定义一个单调栈
int l[N], r[N];   //存一下左右第一个比它小的数//确定下边界之后,如果求最大的面积
int work(int h[])
{//定义两个哨兵,最左边再画一个高度是-1,右边也是,这样对于每个格子,即使高度是0,左右也会存在一个比它小的,这样不需要特判边界h[0] = h[m + 1] = -1;top = 0;   //单调栈的栈先初始化为0//预处理左边stk[++ top] = 0;  //把左边界加进去for (int i = 1; i <= m; i ++){//栈顶元素大于等于当前元素,就把栈顶元素弹出while (h[stk[top]] >= h[i]) top --;//左边第一个比当前元素小的元素就是栈顶元素l[i] = stk[top];//将当前元素加到栈当中stk[++ top] = i;}//同理预处理右边top = 0;stk[++ top] = m + 1;for (int i = m; i; i --){while (h[stk[top]] >= h[i]) top --;r[i] = stk[top];stk[++ top] = i;}//定义一下答案int res = 0;//枚举一下最高点for (int i = 1; i <= m; i ++)res = max(res, h[i] * (r[i] - l[i] - 1));return res;
}int main()
{//读入行数列数和被破坏矩形的数量scanf("%d%d%d", &n, &m, &P);//接下来读入每一个被破坏的位置while (P --){int x, y;scanf("%d%d", &x, &y);g[x][y] = 1;   //如果被破坏的话,标记成1}//预处理h数组for (int i = 1; i <= n; i ++)for (int j = 1; j <= m; j ++)//如果当前的格子没有被破坏if (!g[i][j])h[i][j] = h[i - 1][j] + 1;//定义答案int res = 0;//枚举一下下边界for (int i = 1; i <= n; i ++)res = max(res, work(h[i]));printf("%d\n", res);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/604006.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML - 请你谈一谈img标签图片和background背景图片的区别

难度级别:中级及以上 提问概率:65% 面试官当然不会问如何使用img标签或者background来加载一张图片,这些知识点都很基础,相信只要从事前端开发一小段时间以后,就可以轻松搞定加载图片的问题。但很多人习惯用img标签,很多人习惯用backgro…

第6章 6.1.1 文本格式化 sprintf函数(MATLAB入门课程)

sprintf函数源自 C 语言标准库中的同名函数&#xff0c;这个函数在 C 语言中用于创建格式化的字符串&#xff0c;且使用频率非常高。作为一门高级编程语言&#xff0c;MATLAB借鉴了 C 语言和其他编程语言中的许多特性和命名惯例。在MATLAB中&#xff0c;sprintf函数主要有两种用…

2024马来西亚电商选品博览会

2024马来西亚电商选品博览会 展会概况 展会名称&#xff1a;2024马来西亚电商选品博览会 主办单位&#xff1a;广东进出口商会 时间:2024.11.29-12.1 地点&#xff1a;马来西亚国际贸易展览中心(MITEC) 展览面积&#xff1a;10000平方米 展会简介 2024马来西亚跨境电商选…

每日一题(leetcode1026):节点与其祖先的最大差值--dfs

考虑到只能计算祖先之间的节点差而不能计算兄弟之间的节点差&#xff0c;所以思考使用dfs来解决该题。 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), ri…

动态代理

动态代理 动态代理和静态代理角色一致。 代理类是动态生成的&#xff0c;不是我们直接写好的。 动态代理分为俩大类&#xff1a;基于接口的动态代理、基于类的动态代理 基于接口&#xff1a;JDK动态代理&#xff08;以下示例就是这个&#xff09; 基于类&#xff1a;cglib jav…

PostgreSQL入门到实战-第六弹

PostgreSQL入门到实战 PostgreSQL查询语句(三)官网地址PostgreSQL概述PostgreSQL中ORDER BY理论PostgreSQL中ORDER BY实操更新计划 PostgreSQL查询语句(三) 官网地址 声明: 由于操作系统, 版本更新等原因, 文章所列内容不一定100%复现, 还要以官方信息为准 https://www.post…

Python高级

不定长参数 位置不定长参数&#xff0c;获取参数args会整合为一个元组 def info(*args):print(arg is, args)print(type(arg) is, type(args))info(1, 2, 3, 4, a, b)# 输出 # arg is (1, 2, 3, 4, a, b) # type(arg) is <class tuple> 关键字不定长参数&#xff0c;&…

OJ 连续数的和 球弹跳高度的计算【C判断是否为完全平方数】【格式输出%g输出全部小数部分】

连续数的和 判断是否为完全平方数有两种方法 1.遍历所有小于该数的整数&#xff0c;有一个满足平方与该数相等&#xff0c;则是完全平方数 2.用sqrt()或pow()函数对该数开方&#xff0c;取整&#xff08;舍去小数部分&#xff09;&#xff0c;再平方&#xff0c;与该数相等则…

【前端】学习路线

1、基础 1.1 HTML 菜鸟教程-主页&#xff1a;https://www.runoob.com/ 可以学习&#xff1a;HTML、CSS、Bootstrap等 1.2 CSS 《通用 CSS 笔记、建议与指导》 1.3 JavaScript 1&#xff09;入门&#xff1a;JavaScript 的基本语法 2&#xff09;进阶&#xff1a;现代 …

技术人的管理【屁股决定脑袋】道阻且长...

时间匆匆&#xff0c;转瞬间已是2024年年中。在这短短的半年里&#xff0c;我从一个纯粹的开发者角色向管理者转变&#xff0c;经历了许多挑战和成长。这段旅程充满了波折和收获&#xff0c;也让我更深刻地体会到管理者的责任与使命&#xff0c;管理公司的中台团队&#xff0c;…

《QT实用小工具·二十一》鼠标十字线

1、概述 源码放在文章末尾 该项目实现了界面绘制十字线并跟随鼠标移动的过程&#xff0c;下面是demo演示&#xff1a; 项目部分代码如下&#xff1a; #ifndef WIDGET_H #define WIDGET_H#include <QWidget>namespace Ui { class Widget; }class Widget : public QWidg…

常见的mq产品和优点

常见的mq产品和优点 一、什么是mq? MQ全称 Message Queue&#xff08;消息队列&#xff09;&#xff0c;是在消息的传输过程中保存消息的容器。多用于分布式系统之间进行通信&#xff0c;解耦。 二、常见的mq产品 RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、MetaMq …