当前位置: 首页 > news >正文

2025牛客暑期多校训练营5_J

2025牛客暑期多校训练营5_J

时限:\(2s\)
内存:\(512MB\)

题目描述

给定一个 \(n×m\) 的二元矩阵,其中 \(1\) 代表黑色单元格,\(0\) 代表白色单元格。每一秒,每个黑色单元格会将其上、下、左、右四个相邻的白色单元格变为黑色。

你可以将最多一个白色单元格变为黑色(将 \(0\) 变为 \(1\)),以最小化整个矩阵完全变黑所需的时间。求出这个最短时间。


输入格式

  • 第一行包含两个整数 \(n\)\(m\) (\(1 ≤ n×m ≤ 2×10^5\)),表示矩阵的行数和列数。
  • 接下来的 \(n\) 行,每行包含 \(m\) 个数字(\(0\)\(1\)),表示矩阵的初始状态。

输出格式

输出一个整数,表示在增加一个黑色单元格后,使整个矩阵变黑所需的最短时间。


思路

看到 \(1 \leq n×m \leq 2×10^5\)
时限只有 \(2s\),因此可以预见应该是\(O(nm)\) 或者是 \(O(nm \log(X))\) 的复杂度。

由于我们肯定要算出每一个白点最早被染黑的时间,得做多源BFS,我们显然不能枚举每一个白点BFS,只能做一次。

即使在不加点的最坏情况下,


现在做完BFS后,答案一定 \(T \leq n+m\),
且一定在 \([0, t_{max}]\) 之间,考虑二分 \(T\)

开始写check
我们可以得到每个白点被染黑的时间 \(t_i\),我们应该要让所有\(t_i > T\)的点变成\(t_i \leq T\),之后称为慢点,

找出所有慢点组成的集合
\(E = {p: Time(p) > T}\),即在 \(T\) 秒内无法被原有黑点染黑的点。
这些点必须依赖新加的黑点 \(c(i,j)\) 才能及时变黑。

即存在一个白点\(c(i,j)\),对于每个 \(p \in E\),要求

\[|p_x - i| + |p_y - j| \leq T \]

\(c\)\(p\) 的曼哈顿距离不超过 \(T\)
这等价于 \(c\) 必须落在以 \(p\) 为中心、半径 \(T\) 的菱形内。

可以将绝对值拆掉,得到四个不等式:

\[p_x -i - p_y + j \leq T \]

\[p_x -i + p_y - j \leq T \]

\[-p_x + i - p_y + j \leq T \]

\[-p_x + i + p_y - j \leq T \]

\(i\)\(j\)作为变量,移项得到:

\[i+j \in [p_x + p_y - T,, p_x + p_y + T] \]

\[i-j \in [p_x - p_y - T,, p_x - p_y + T] \]

那么所有慢点的交集就是:

\[i+j \in [L_1, R_1] \]

\[i-j \in [L_2, R_2] \]

其中

\[L_1 = \max_{p \in E}(p_x + p_y - T) \]

\[R_1 = \min_{p \in E}(p_x + p_y + T) \]

\[L_2 = \max_{p \in E}(p_x - p_y - T) \]

\[R_2 = \min_{p \in E}(p_x - p_y + T) \]

可以\(O(nm)\)地计算出 \(L_1, R_1, L_2, R_2\)

之后就是只要找到一个这样的点就可以了。
也可以\(O(nm)\)地遍历所有白点。
只要存在一个原本为白色的格子 \((i, j)\),满足 \(i+j \in [L_1, R_1]\)\(i-j \in [L_2, R_2]\),就可以在 \(T\) 秒内全部染黑。
如果 \(E\) 为空(即所有点本来就能在 \(T\) 秒内变黑),直接返回true。

复杂度 \(O(nm\log(nm))\)


#include <bits/stdc++.h>
using namespace std;
using ll = long long;int main()
{ios::sync_with_stdio(false);cin.tie(nullptr);int n, m;cin >> n >> m;vector<vector<int>> mp(n, vector<int>(m));const int INF = 1e9;for (int i = 0; i < n; i++)for (int j = 0; j < m; j++)cin >> mp[i][j];vector<vector<int>> D(n, vector<int>(m, INF));queue<pair<int, int>> q;for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){if (mp[i][j] == 1){D[i][j] = 0;q.push({i, j});}}}int dirs[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};while (!q.empty()){auto [x, y] = q.front();q.pop();for (auto &d : dirs){int nx = x + d[0], ny = y + d[1];if (nx >= 0 && nx < n && ny >= 0 && ny < m && D[nx][ny] > D[x][y] + 1){D[nx][ny] = D[x][y] + 1;q.push({nx, ny});}}}int tm = 0;for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){tm = max(tm, D[i][j]);}}auto letmeseesee = [&](int T) -> bool{int L1 = -1e9, R1 = 1e9, L2 = -1e9, R2 = 1e9;bool ok = false;for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){if (D[i][j] > T){ok = true;L1 = max(L1, i + j - T);R1 = min(R1, i + j + T);L2 = max(L2, i - j - T);R2 = min(R2, i - j + T);}}}if (!ok)return 1;for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){if (mp[i][j] == 0){int sum = i + j, diff = i - j;if (sum >= L1 && sum <= R1 && diff >= L2 && diff <= R2)return 1;}}}return 0;};int lo = 0, hi = tm;int ans = hi;while (lo <= hi){int mid = (lo + hi) / 2;if (letmeseesee(mid)){ans = mid;hi = mid - 1;}else{lo = mid + 1;}}cout << ans << "\n";return 0;
}
http://www.vanclimg.com/news/1414.html

相关文章:

  • 【LeetCode 24】力扣算法:两两交换链表中的节点
  • Pwn2Own柏林2025:第三天赛事成果与技术漏洞全记录
  • POLIR-Laws-民事诉讼法:手机录音能否作为民事诉讼证据?怎么录音才能被法院采信?
  • MCP是如何工作的?
  • OBS
  • 屏幕翻译 安卓app
  • 微算法科技(NASDAQ:MLGO)应用区块链联邦学习(BlockFL)架构,实现数据的安全传输
  • 星球助手发布更新 v1.7.0
  • 使用Spring Cloud和Resilience4j实现微服务容错与降级 - spiderMan1
  • WinForm自定义控件实现类似百度网盘客户端菜单组件
  • 【比赛记录】2025CSP-S模拟赛29
  • 树形dp练习
  • python中 命令行参数解析模块 argparse
  • 基于YOLOv8的狗狗品种(多达60种常见犬类)品种鉴别识别项目|完整源码数据集+PyQt5界面+完整训练流程+开箱即用!
  • 公钥和私钥的部分作用
  • 使用 Kiro AI IDE 3小时实现全栈应用Admin系统
  • soildworks建模界面添加图片
  • 从0开始构建技术
  • Fastmcp 案例二(SSe)
  • Anaconda历史版本
  • 输入未知数目的数据
  • 常见的结构光编解码算法
  • 七月
  • HCIE学习之路:一个NAT实验
  • HCIE学习之路:配置基于静态路由的GRE隧道
  • TOP10迪士尼动画电影下载_公主系列迪士尼电影大全列表在线观看
  • python中pandas包的基本用法
  • 如何用两年时间面试一个人(by jobleap.cn)
  • 2025年PLM合规性管理,6大策略,确保项目合法合规!
  • 如果你还有一些困惑 / 请贴着我的心倾听 - Urd