Problem:
B: Hokkaido University Hard

注意

　問題設定は A 問題と同一のものですが、制約のみが異なりますのでご注意ください。

物語

　北海道大学に合格し、新たな生活の始まりに心を躍らせるほむらちゃん。しかし彼女の前には、とてつもなく広いキャンパスが待ち受けていた...。

　「え...次の授業に間に合わないんだけど...」

問題

　北海道大学札幌キャンパスは異常に広いことで有名です。札幌キャンパスは縦に H マス、横に W マス並んだ長方形のマス目で表現されます。北から i マス、西から j マス進んだマスを (i,j) で表すことにします。キャンパス内にはいくつか建物があり、マス (i,j) で表される位置に建物がある場合は 'B' 、ない場合は '.' が c_{i,j} に書かれています。

　北海道大学の新入生のほむらちゃんは、キャンパスのあまりの広さに驚愕し、建物間の移動が心配になってきました。そこで、建物のある 2 つのマスのうち、最も遠い組はどれくらい離れているのかが気になりました。ここで、2 つのマスの組 (i,j) , (i',j') の間の距離を |i-i'|+|j-j'| と定義します。

　ほむらちゃんは、自分にはこの問題は難しいと思い、同級生のあなたに助けを求めてきました。ほむらちゃんの代わりに答えを求めてください。

入力形式

H W
c_{11}c_{12} ... c_{1W}
:
c_{H1}c_{H2} ... c_{HW}

制約

2 \leq H,W \leq 10^3

H,W は整数

c_{i,j} は 'B' か '.' のいずれかである。

c_{i,j} のうち少なくとも 2 つは 'B' である。

出力形式

答えを表す整数を 1 行に出力せよ。

入力例 1

3 3
B.B
..B
.BB

出力例 1

4

(1,1) と (3,3) の 2 点間が最長です。

入力例 2

4 3
B..
B..
...
...

出力例 2

1

隣り合う位置が最長になる場合もあります。

入力例 3

6 6
...B..
B.B.B.
.B.B.B
...B.B
.B..B.
..B...

出力例 3

7

Solution in Rust (judge verdict: Accepted)

#[allow(unused_imports)]
use std::cmp::*;
#[allow(unused_imports)]
use std::collections::*;
use std::io::{Write, BufWriter};
// https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8
macro_rules! input {
    ($($r:tt)*) => {
        let stdin = std::io::stdin();
        let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));
        let mut next = move || -> String{
            bytes
                .by_ref()
                .map(|r|r.unwrap() as char)
                .skip_while(|c|c.is_whitespace())
                .take_while(|c|!c.is_whitespace())
                .collect()
        };
        input_inner!{next, $($r)*}
    };
}

macro_rules! input_inner {
    ($next:expr) => {};
    ($next:expr, ) => {};

    ($next:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };
}

macro_rules! read_value {
    ($next:expr, ( $($t:tt),* )) => {
        ( $(read_value!($next, $t)),* )
    };

    ($next:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
    };

    ($next:expr, chars) => {
        read_value!($next, String).chars().collect::<Vec<char>>()
    };

    ($next:expr, usize1) => {
        read_value!($next, usize) - 1
    };

    ($next:expr, [ $t:tt ]) => {{
        let len = read_value!($next, usize);
        (0..len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
    }};

    ($next:expr, $t:ty) => {
        $next().parse::<$t>().expect("Parse error")
    };
}

fn solve() {
    let out = std::io::stdout();
    let mut out = BufWriter::new(out.lock());
    macro_rules! puts {
        ($($format:tt)*) => (write!(out,$($format)*).unwrap());
    }
    input! {
        h: usize, w: usize,
        a: [chars; h],
    }
    const INF: i64 = 1 << 40;
    let mut mia = INF;
    let mut mib = INF;
    let mut maa = -INF;
    let mut mab = -INF;
    for i in 0..h {
        for j in 0..w {
            if a[i][j] != 'B' { continue; }
            let a = i as i64 + j as i64;
            let b = i as i64 - j as i64;
            mia = min(mia, a);
            maa = max(maa, a);
            mib = min(mib, b);
            mab = max(mab, b);
        }
    }
    puts!("{}\n", max(mab - mib, maa - mia));
}

fn main() {
    // In order to avoid potential stack overflow, spawn a new thread.
    let stack_size = 104_857_600; // 100 MB
    let thd = std::thread::Builder::new().stack_size(stack_size);
    thd.spawn(|| solve()).unwrap().join().unwrap();
}