Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) E. Arson In Berland Forest 二分 前缀和
E. Arson In Berland Forest
The Berland Forest can be represented as an infinite cell plane. Every cell contains a tree. That is, contained before the recent events.
A destructive fire raged through the Forest, and several trees were damaged by it. Precisely speaking, you have a n×m rectangle map which represents the damaged part of the Forest. The damaged trees were marked as "X" while the remaining ones were marked as ".". You are sure that all burnt trees are shown on the map. All the trees outside the map are undamaged.
The firemen quickly extinguished the fire, and now they are investigating the cause of it. The main version is that there was an arson: at some moment of time (let's consider it as 0) some trees were set on fire. At the beginning of minute 0, only the trees that were set on fire initially were burning. At the end of each minute, the fire spread from every burning tree to each of 8 neighboring trees. At the beginning of minute T, the fire was extinguished.
The firemen want to find the arsonists as quickly as possible. The problem is, they know neither the value of T (how long the fire has been raging) nor the coordinates of the trees that were initially set on fire. They want you to find the maximum value of T (to know how far could the arsonists escape) and a possible set of trees that could be initially set on fire.
Note that you'd like to maximize value T but the set of trees can be arbitrary.
Input
The first line contains two integer n and m (1≤n,m≤106, 1≤n⋅m≤106) — the sizes of the map.
Next n lines contain the map. The i-th line corresponds to the i-th row of the map and contains m-character string. The j-th character of the i-th string is "X" if the corresponding tree is burnt and "." otherwise.
It's guaranteed that the map contains at least one "X".
Output
In the first line print the single integer T — the maximum time the Forest was on fire. In the next n lines print the certificate: the map (n×m rectangle) where the trees that were set on fire are marked as "X" and all other trees are marked as ".".
Examples
input
3 6
XXXXXX
XXXXXX
XXXXXX
output
1
......
.X.XX.
......
input
10 10
.XXXXXX...
.XXXXXX...
.XXXXXX...
.XXXXXX...
.XXXXXXXX.
...XXXXXX.
...XXXXXX.
...XXXXXX.
...XXXXXX.
..........
output
2
..........
..........
...XX.....
..........
..........
..........
.....XX...
..........
..........
..........
input
4 5
X....
..XXX
..XXX
..XXX
output
0
X....
..XXX
..XXX
..XXX
题意
现在有个地方发生了火灾,火焰每秒都会往上下左右对角线八个方向进行蔓延。
现在给你最终的火焰图,你想使得燃烧的时间最长,问你最开始的火焰是什么样的。
题解
最暴力的做法是我把当前没燃烧的点加进队列里面,然后每秒用bfs去模拟熄灭的过程。
那么什么时候不能熄灭了呢,就是我熄灭后再蔓延不能得到之前的样子的时候,就是不能再熄灭了。
暴力会T,所以我们得改成二分。
二分+bfs其实也会T,会被卡常数,所以最好改成前缀和的。前缀和的话,火焰从中间向八个方向燃烧,改成向三个方向燃烧的前缀和做法。
具体看代码。
代码
#include<bits/stdc++.h>
using namespace std;
int main() {
ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int N, M; cin >> N >> M;
vector<string> G(N);
for (int i = 0; i < N; i++) {
cin >> G[i];
}
vector<vector<int>> maxSquare(N, vector<int>(M));
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (G[i][j] == '.') maxSquare[i][j] = 0;
else if (i == 0 || j == 0) {
maxSquare[i][j] = 1;
} else {
maxSquare[i][j] = 1 + min(maxSquare[i-1][j-1], min(maxSquare[i-1][j], maxSquare[i][j-1]));
}
}
}
vector<vector<int>> coverDist(N, vector<int>(M));
int mi = 0;
int ma = int(2e6);
while (ma - mi > 1) {
int md = (mi + ma) / 2;
int s = 2 * md + 1;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (maxSquare[i][j] >= s) {
coverDist[i][j] = s;
} else {
coverDist[i][j] = 0;
}
}
}
for (int i = N-1; i >= 0; i--) {
for (int j = M-1; j >= 0; j--) {
if (i > 0) {
coverDist[i-1][j] = max(coverDist[i-1][j], coverDist[i][j] - 1);
}
if (j > 0) {
coverDist[i][j-1] = max(coverDist[i][j-1], coverDist[i][j] - 1);
}
if (i > 0 && j > 0) {
coverDist[i-1][j-1] = max(coverDist[i-1][j-1], coverDist[i][j] - 1);
}
}
}
bool isGood = true;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (G[i][j] == '.') continue;
if (coverDist[i][j] == 0) isGood = false;
}
}
if (isGood) {
mi = md;
} else {
ma = md;
}
}
cout << mi << '\n';
int s = 2 * mi + 1;
vector<string> ans(N, string(M, '.'));
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if (maxSquare[i][j] >= s) {
ans[i - mi][j - mi] = 'X';
}
}
}
for (int i = 0; i < N; i++) {
cout << ans[i] << '\n';
}
return 0;
}
Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) E. Arson In Berland Forest 二分 前缀和的更多相关文章
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3
A,有多个线段,求一条最短的线段长度,能过覆盖到所又线段,例如(2,4)和(5,6) 那么我们需要4 5连起来,长度为1,例如(2,10)(3,11),用(3,10) 思路:我们想一下如果题目说的是最 ...
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) F2. Wrong Answer on test 233 (Hard Version) dp 数学
F2. Wrong Answer on test 233 (Hard Version) Your program fails again. This time it gets "Wrong ...
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) D2. Optimal Subsequences (Hard Version) 数据结构 贪心
D2. Optimal Subsequences (Hard Version) This is the harder version of the problem. In this version, ...
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) C. Messy 构造
C. Messy You are fed up with your messy room, so you decided to clean it up. Your room is a bracket ...
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) B. Box 贪心
B. Box Permutation p is a sequence of integers p=[p1,p2,-,pn], consisting of n distinct (unique) pos ...
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) A. Math Problem 水题
A. Math Problem Your math teacher gave you the following problem: There are n segments on the x-axis ...
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) C Messy
//因为可以反转n次 所以可以得到任何可以构成的序列 #include<iostream> #include<string> #include<vector> us ...
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) B Box
#include<bits/stdc++.h> using namespace std; ]; ]; int main() { int total; cin>>total; w ...
- Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) A Math Problem
//只要从所有区间右端点的最小值覆盖到所有区间左端点的最大值即可 #include<iostream> using namespace std ; int x,y; int n; int ...
随机推荐
- Docker容器镜像打成tar包
简述需求: 在现在容器上保存镜像进行打包,在另一台服务上使用 首先查看下现有要打tar包的容器 docker ps -a 接下来用commit参数进行保存镜像, -a 提交人的姓名 -m “提交内容 ...
- Chrome 开发者工具实用操作
Chrome 开发者工具实用操作 https://umaar.com/dev-tips/
- 梁敬彬老师的《收获,不止SQL优化》,关于如何缩短SQL调优时间,给出了三个步骤,
梁敬彬老师的<收获,不止SQL优化>,关于如何缩短SQL调优时间,给出了三个步骤, 1. 先获取有助调优的数据库整体信息 2. 快速获取SQL运行台前信息 3. 快速获取SQL关联幕后信息 ...
- COUNT(*)、COUNT(主键)、COUNT(1)
MyISAM引擎,记录数是结构的一部分,已存cache在内存中; InnoDB引擎,需要重新计算,id是主键的话,会加快扫描速度: 所以select count(*) MyISAM完胜! MyISA ...
- asp.net实现SQL2005的通知数据缓存
首先第一步是确保您的 Service Broker 已经激活,激活 Service Broker (Transact-SQL)如下: USE master ; GO ALTER DATABASE Yo ...
- 由随机数rand5实现随机数rand7
rand5表示生成随机数1,2,3,4,5 rand7表示生成随机数1,2,3,4,5,6,7 要通过rand5构造rand7现在可能没有什么思路,我们先试着用rand7生成rand5 rand7生成 ...
- 【Golang基础】defer执行顺序
defer 执行顺序类似栈的先入后出原则(FILO) 一个defer引发的小坑:打开文件,读取内容,删除文件 // 原始问题代码 func testFun(){ // 打开文件 file, ...
- 一篇和Redis有关的锁和事务的文章
部分参考链接 Transaction StackExchange.Redis Transaction hashest 正文 Redis 是一种基于内存的单线程数据库.意味着所有的命令是一个接一个的执行 ...
- ubuntu 18.04多应用窗口切换的快捷键使用指南
前记 使用ubuntu时间长了,很厌烦用鼠标来点来点去.重复操作的,还是快捷键比较方便.在多窗口切换方面,熟悉了几个快捷键之后,顿时感觉神清气爽.这里就推荐给大家学习一下,提高工作效率啊. 常用快捷键 ...
- 《How Tomcat works》
容器是一个处理用户servlet请求并返回对象给web用户的模块. org.apache.catalina.Container接口定义了容器的形式,用四种容器:Engine(引擎),Host(主机), ...