Problem:
Score : 500 points

Problem Statement

AtCoDeer is thinking of painting an infinite two-dimensional grid in a checked pattern of side K.
Here, a checked pattern of side K is a pattern where each square is painted black or white so that each connected component of each color is a K × K square.
Below is an example of a checked pattern of side 3:

AtCoDeer has N desires.
The i-th desire is represented by x_i, y_i and c_i.
If c_i is B, it means that he wants to paint the square (x_i,y_i) black; if c_i is W, he wants to paint the square (x_i,y_i) white.
At most how many desires can he satisfy at the same time?

Constraints

1 ≤ N ≤ 10^5

1 ≤ K ≤ 1000

0 ≤ x_i ≤ 10^9

0 ≤ y_i ≤ 10^9

If i ≠ j, then (x_i,y_i) ≠ (x_j,y_j).

c_i is B or W.

N, K, x_i and y_i are integers.

Input

Input is given from Standard Input in the following format:

N K
x_1 y_1 c_1
x_2 y_2 c_2
:
x_N y_N c_N

Output

Print the maximum number of desires that can be satisfied at the same time.

Sample Input 1

4 3
0 1 W
1 2 W
5 3 B
5 4 B

Sample Output 1

4

He can satisfy all his desires by painting as shown in the example above.

Sample Input 2

2 1000
0 0 B
0 1 W

Sample Output 2

2

Sample Input 3

6 2
1 2 B
2 1 W
2 2 B
1 0 B
0 6 W
4 5 W

Sample Output 3

4

Solution in Rust (1.15.1) (judge verdict: Accepted)

#![allow(unused_imports, unused_macros, unknown_lints)]

use std::collections::*;
use std::cmp::Ordering::*;

macro_rules! dump {($($e:expr), +) => {print!(concat!($(stringify!($e), " = {:?}\n"), +), $($e), +)}}
macro_rules! max {($e0:expr, $($e:expr), +) => {{let mut r = $e0; $(r = std::cmp::max(r, $e);)+ r}}}
macro_rules! min {($e0:expr, $($e:expr), +) => {{let mut r = $e0; $(r = std::cmp::min(r, $e);)+ r}}}

fn main() {
  let (n,k) = get::tuple::<usize,usize>();
  let xycs = get::tuple3s::<usize,usize,String>(n);

  let xys =
    xycs.iter().
    map(|&(x,y,ref c)|if &c[..]=="W" {((x+k)%(2*k),y%(2*k))} else {(x%(2*k),y%(2*k))}).
    collect::<Vec<_>>();
  
  let mut mat = vec![vec![0; 2*k]; 2*k];
  for &(x,y) in &xys {mat[x][y] += 1}
  
  let mut grid = Grid::new(mat, 0);
  grid.accumulate();
  
  let offset = |p,d| {
    let q = p + d as isize;
    if q < 1 {0} else if q > 2 * k as isize {2*k+1} else {q as usize}
  };
  
  // if k==1 {dump!(grid.height, grid.width); grid.print()}

  let mut ans = 0;
  for i in 0 .. 2*k {
    for j in 0 .. 2*k {
      let k = k as isize;
      let sum_c  = grid.sum(offset(1,i),offset(1,j),offset(k,i),offset(k,j));
      let sum_w  = grid.sum(offset(1-2*k,i),offset(1,j),offset(k-2*k,i),offset(k,j));
      let sum_s  = grid.sum(offset(1,i),offset(1-2*k,j),offset(k,i),offset(k-2*k,j));
      let sum_nw = grid.sum(offset(1-k,i),offset(1+k,j),offset(k-k,i),offset(k+k,j));
      let sum_ne = grid.sum(offset(1+k,i),offset(1+k,j),offset(k+k,i),offset(k+k,j));
      let sum_sw = grid.sum(offset(1-k,i),offset(1-k,j),offset(k-k,i),offset(k-k,j));
      let sum_se = grid.sum(offset(1+k,i),offset(1-k,j),offset(k+k,i),offset(k-k,j));
      // if k==1 {dump!(sum_c,sum_w,sum_s,sum_nw,sum_ne,sum_sw,sum_se)}
      ans = max!(ans, sum_c + sum_w + sum_s + sum_nw + sum_ne + sum_sw + sum_se)
    }
  }
  
  println!("{}", ans)
}

struct Grid {
  height: usize,
  width: usize,
  mat: Vec<Vec<isize>>
}

#[allow(dead_code)]
impl Grid {
  fn new(mat: Vec<Vec<isize>>, b: isize) -> Grid {
    let h = mat.len();
    let w = mat[0].len();
    let mut m = mat;

    for v in m.iter_mut() {
      v.insert(0, b);
      v.push(b)
    }
    let bs = (0..w+2).map(|_|b).collect::<Vec<_>>();
    m.insert(0, bs.clone());
    m.push(bs);

    Grid {height: h, width: w, mat: m}
  }
 
  fn get(&self, i: usize, j: usize) -> isize {
    self.mat[i][j]
  }
 
  fn put(&mut self, i: usize, j: usize, x: isize) {
    self.mat[i][j] = x
  }
 
  fn accumulate(&mut self) {
    for i in 1 .. self.height + 1 {
      for j in 1 .. self.width + 1 {
        self.mat[i][j] += self.mat[i][j-1]
      }
    }
    for i in 1 .. self.height + 1 {
      for j in 1 .. self.width + 1 {
        self.mat[i][j] += self.mat[i-1][j]
      }
    }
  }
 
  fn sum(&self, x1: usize, y1: usize, x2: usize, y2: usize) -> isize {
    if x1>self.height || y1>self.width {return 0}
    let x1 = if x1 <= 0 {0} else {x1-1};
    let y1 = if y1 <= 0 {0} else {y1-1};
    let x2 = if x2 > self.height {self.height} else {x2};
    let y2 = if y2 > self.width {self.width} else {y2};
    self.mat[x2][y2] - self.mat[x1][y2] - self.mat[x2][y1] + self.mat[x1][y1]
  }
 
  fn print(&self) {
    for v in self.mat[1 .. self.height+1].iter() {
      let out = &v[1..self.width+1].iter().map(|e|format!("{:?}",e)).collect::<Vec<_>>().as_slice().join(" ");
      println!("{}", out);
    }
  }
}

#[allow(dead_code)]
mod get {
  use std::io::*;
  use std::str::*;
  use std::process::*;

  pub fn val<T: FromStr>() -> T {
    let mut buf = String::new();
    let s = stdin();
    s.lock().read_line(&mut buf).ok();
    if buf.is_empty() {println!("No input"); exit(0)}
    buf.trim_right().parse::<T>().ok().unwrap()
  }

  pub fn vals<T: FromStr>(n: usize) -> Vec<T> {
    let mut vec: Vec<T> = vec![];
    for _ in 0 .. n {
      vec.push(val());
    }
    vec
  }

  pub fn tuple<T1: FromStr, T2: FromStr>() -> (T1, T2) {
    let mut buf = String::new();
    let s = stdin();
    s.lock().read_line(&mut buf).ok();
    if buf.is_empty() {println!("No input"); exit(0)}
    let mut it = buf.trim_right().split_whitespace();
    let x = it.next().unwrap().parse::<T1>().ok().unwrap();
    let y = it.next().unwrap().parse::<T2>().ok().unwrap();
    (x, y)
  }

  pub fn tuples<T1: FromStr, T2: FromStr>(n: usize) -> Vec<(T1, T2)> {
    let mut vec: Vec<(T1, T2)> = vec![];
    for _ in 0 .. n {
      vec.push(tuple());
    }
    vec
  }

  pub fn tuple3<T1: FromStr, T2: FromStr, T3: FromStr>() -> (T1, T2, T3) {
    let mut buf = String::new();
    let s = stdin();
    s.lock().read_line(&mut buf).ok();
    if buf.is_empty() {println!("No input"); exit(0)}
    let mut it = buf.trim_right().split_whitespace();
    let x = it.next().unwrap().parse::<T1>().ok().unwrap();
    let y = it.next().unwrap().parse::<T2>().ok().unwrap();
    let z = it.next().unwrap().parse::<T3>().ok().unwrap();
    (x, y, z)
  }

  pub fn tuple3s<T1: FromStr, T2: FromStr, T3: FromStr>(n: usize) -> Vec<(T1, T2, T3)> {
    let mut vec: Vec<(T1, T2, T3)> = vec![];
    for _ in 0 .. n {
      vec.push(tuple3());
    }
    vec
  }

  pub fn vec<T: FromStr>() -> Vec<T> {
    let mut buf = String::new();
    let s = stdin();
    s.lock().read_line(&mut buf).ok();
    if buf.is_empty() {println!("No input"); exit(0)}
    buf.trim_right().split_whitespace().map(|t| t.parse::<T>().ok().unwrap()).collect()
  }

  pub fn mat<T: FromStr>(h: usize) -> Vec<Vec<T>> {
    let mut mat = vec![];
    for _ in 0 .. h {
      mat.push(vec());
    }
    mat
  }

  pub fn chars() -> Vec<char> {
    let mut buf = String::new();
    let s = stdin();
    s.lock().read_line(&mut buf).ok();
    if buf.is_empty() {println!("No input"); exit(0)}
    buf.trim_right().chars().collect()
  }
}

#[allow(dead_code)]
mod put {
  use std::string::*;

  pub fn vec<T: ToString>(vec: &Vec<T>, sep: &str) {
    let out = vec.iter().map(|e| e.to_string()).collect::<Vec<_>>().as_slice().join(sep);
    println!("{}", out);
  }

  pub fn mat<T: ToString>(mat: &Vec<Vec<T>>, sep: &str) {
    for v in mat {
      vec(v, sep);
    }
  }
}