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×mn×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 00) some trees were set on fire. At the beginning of minute 00, 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 88 neighboring trees. At the beginning of minute TT, the fire was extinguished.

The firemen want to find the arsonists as quickly as possible. The problem is, they know neither the value of TT (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 TT (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 TT but the set of trees can be arbitrary.

Input

The first line contains two integer nn and mm (1≤n,m≤1061≤n,m≤106, 1≤n⋅m≤1061≤n⋅m≤106) — the sizes of the map.

Next nn lines contain the map. The ii-th line corresponds to the ii-th row of the map and contains mm-character string. The jj-th character of the ii-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 TT — the maximum time the Forest was on fire. In the next nn lines print the certificate: the map (n×mn×m rectangle) where the trees that were set on fire are marked as "X" and all other trees are marked as ".".

Examples
input

Copy
3 6
XXXXXX
XXXXXX
XXXXXX
output

Copy
1
......
.X.XX.
......
input

Copy
10 10
.XXXXXX...
.XXXXXX...
.XXXXXX...
.XXXXXX...
.XXXXXXXX.
...XXXXXX.
...XXXXXX.
...XXXXXX.
...XXXXXX.
..........
output

Copy
2
..........
..........
...XX.....
..........
..........
..........
.....XX...
..........
..........
..........
input

Copy
4 5
X....
..XXX
..XXX
..XXX
output

Copy
0
X....
..XXX
..XXX
..XXX

题意:给一个n*m<=1e6的图,"X"代表着火,"."代表没着火,火只在这个范围里面蔓延。着火的格子每回合会蔓延到周围的8个格子,给出了最后的火情图,求着火最多多少回合,并构造刚着火的图。

想法:很明显蔓延后的火都是一个矩形,所以我先横着遍历1遍,再竖着遍历遍,基本可以确认这个火最多蔓延了多少回合,构造图通过前缀和来判断,比较简单。然后我就被这组数据卡住了

7 5
..XXX
..XXX
..XXX
.XXX.
XXX..
XXX..
XXX.. 我一开始的输出
1
.....
...X.
.....
.....
.....
.X...
.....
答案
0
..XXX
..XXX
..XXX
.XXX.
XXX..
XXX..
XXX..

被这个数据卡住是因为,横着扫一遍竖着扫一遍只能确定最多蔓延回合不会超过这个数值,但是构造出来的图不一定能蔓延回原来的图。

做法:二分答案,先记录终图的前缀和,然后构造起始图,该点为"X"意味着终图中以该点为中心的m范围全为"X",用二维前缀和来判断。否则为"."。构造的同时记录起始图的前缀和。

构造完起始图后我们再检查初始是否合法,同样是用前缀和,该点为"X"意味着起始图中以该点为中心的m范围有"X"或者该点为"."意味着起始图中以该点为中心的m范围。

分析复杂度,每次二分我们需要构造1次和检查1次,复杂度是2e6。对于1e6的图需要二分20次复杂度是4e7,分析可得,蔓延最大不会超过1000回合,只需二分10次,复杂度变2e7。而横着扫一遍竖着扫一遍可以确定二分上界,这个操作复杂度是2e6,这样比纯二分快点。。

#include <bits/stdc++.h>
using namespace std;
const int N=2e6+;
char p[N];
char v[N];
int u[N];
int z[N];
int n,m;
inline bool solve(int zd)
{
for(int i=;i<=n;++i)
{
for(int j=;j<=m;++j)
{
int t=i*(m+)+j;
v[t]='.';
if(p[t]=='X')
{
int flag=;
int rx=i+zd;
int ry=j+zd;
int lx=i-zd;
int ly=j-zd;
if(rx>n||ry>m||lx<=||ly<=)flag=;
if((u[rx*(m+)+ry]-u[rx*(m+)+ly-]-u[(lx-)*(m+)+ry])+u[(lx-)*(m+)+ly-]!=((zd*+)*(zd*+)))flag=;
if(!flag)v[t]='X';
}
z[t]=(v[t]=='X'?:)+z[t-]+z[t-m-]-z[t-m-];
}
}
for(int i=;i<=n;++i)
{
for(int j=;j<=m;++j)
{
int t=i*(m+)+j;
if(p[t]=='X')
{
int rx=i+zd;
int ry=j+zd;
int lx=i-zd;
int ly=j-zd;
if(rx>n||ry>m||lx<=||ly<=)continue;
if((z[rx*(m+)+ry]-z[rx*(m+)+ly-]-z[(lx-)*(m+)+ry]+z[(lx-)*(m+)+ly-])==)return false;
}
}
}
return true;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i)
{
for(int j=;j<=m;++j)
{
int t=i*(m+)+j;
scanf(" %c",&p[t]);
u[t]=(p[t]=='X'?:)+u[t-]+u[t-m-]-u[t-m-];
}
}
int zd=;
for(int i=;i<=n;++i)
{
for(int j=;j<=m;++j)
{
int t=;
while(p[i*(m+)+j]=='X')
{
j++;
t++;
if(j==m+)break;
}
if(t&&zd>t)zd=t;
}
}
for(int i=;i<=m;++i)
{
for(int j=;j<=n;++j)
{
int t=;
while(p[i+j*(m+)]=='X')
{
j++;
t++;
if(j==n+)break;
}
if(t&&zd>t)zd=t;
}
}
zd=(zd-)/;
if(zd==)
{
printf("0\n");
for(int i=;i<=n;++i)
{
for(int j=;j<=m;++j)printf("%c",p[i*(m+)+j]);
printf("\n");
}
return ;
}
int l=,r=zd;
int ans=;
while(l<=r)
{
int m=(l+r)>>;
if(solve(m))
{
l=m+;
ans=m;
}
else r=m-;
}
printf("%d\n",ans);
solve(ans);
for(int i=;i<=n;++i)
{
for(int j=;j<=m;++j)printf("%c",v[i*(m+)+j]);
printf("\n");
}
return ;
}

代码

总结:直接开二维数组不可取,我是用了一维的来表示二维的,用vector应该会方便不少。然后就是要多练,此外对题目的复述要准确,问人时完全描述成了另一道题。。这都是值得努力的地方

Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) E. Arson In Berland Forest的更多相关文章

  1. 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) 思路:我们想一下如果题目说的是最 ...

  2. 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 ...

  3. 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 ce ...

  4. 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, ...

  5. 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 ...

  6. 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 ...

  7. 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 ...

  8. Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) C Messy

    //因为可以反转n次 所以可以得到任何可以构成的序列 #include<iostream> #include<string> #include<vector> us ...

  9. 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 ...

  10. 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 ...

随机推荐

  1. 指定GPU运行python程序

    一.命令行运行python程序时 1.首先查看哪些GPU空闲,nvidia-smi显示当前GPU使用情况. nvidia-smi 2.然后指定空闲的GPU运行python程序. CUDA_VISIBL ...

  2. python的线性代数

    估计线性模型中的系数:a=np.linalg.lstsq(x,b),有b=a*x 求方阵的逆矩阵np.linalg.inv(A) 求广义逆矩阵:np.linalg.pinv(A) 求矩阵的行列式:np ...

  3. _CrtIsValidHeapPointer(pUserData)

    程序遇到如题的运行时报错,参考下面这段文字,采取将自定义类的对象定义改为new方式生成后问题解决. !!Expression: _CrtIsValidHeapPointer(pUserData) vo ...

  4. 转:Nginx 性能优化有这篇就够了!

    目录: https://mp.weixin.qq.com/s/YoZDzY4Tmj8HpQkSgnZLvA 1.Nginx运行工作进程数量 Nginx运行工作进程个数一般设置CPU的核心或者核心数x2 ...

  5. iScroll.js的用法

    概要 iScroll 4 这个版本完全重写了iScroll这个框架的原始代码.这个项目的产生完全是因为移动版webkit浏览器(诸如iPhone,iPad,Android 这些系统上广泛使用)提供了一 ...

  6. Slim安装以及使用

    最近在用backbone.js 做东西,因为牵扯到REST services 所以需要后台支持,此处选择了php.Slim 是php的一个框架. 貌似国内文章对此的介绍比较少,在安装Slim的过程中出 ...

  7. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 辅助类:"text-primary" 类的文本样式

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  8. 在Anaconda3环境下安装并切换 Tensorflow 2.0 环境

    背景 Anaconda切换各种环境非常方便,现在我们就来介绍一下如何使用anaconda安装tensorflow环境. anaconda v3.5 from 清华镜像站 tensorflow v2.0 ...

  9. 【LeetCode】基本计算器II

    [问题]实现一个基本的计算器来计算一个简单的字符串表达式的值.字符串表达式仅包含非负整数,+, - ,*,/ 四种运算符和空格  .整数除法仅保留整数部分. 输入: "3+2*2" ...

  10. 洛谷 P5509 派遣

    题目传送门 心路历程: 每想到一种思路,就有一种要做出来的感觉.但一接着想就会发现这种方法有一些极小的问题,但是我没法解决... 于是就再换思路... 最后在请教了出题人神仙zcq之后,终于做出来了 ...