Problem p03458 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for (int i = (l); i < (r); ++i)
typedef long long ll;
typedef unsigned long long ull;
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}

/* attention
    long longのシフト演算には気をつけよう
    タイポした時のデバッグが死ぬほどきつくなるので変数名は最低3字くらい使った方がいいかも
    sizeは(int)とキャストしよう
    ごちゃごちゃ場合分けを考える前に全探索は考えましたか？
*/

const ll mod = 1e9 + 7;

void chmod(ll &M) {
  if (M >= mod)
    M %= mod;
  else if (M < 0) {
    M += (abs(M) / mod + 1) * mod;
    M %= mod;
  }
}

ll modpow(ll x, ll n) {
  if (n == 0)
    return 1;

  ll res = modpow(x, n / 2);
  if (n % 2 == 0)
    return res * res % mod;
  else
    return res * res % mod * x % mod;
}

ll power(ll x, ll n) {
  if (n == 0)
    return 1;

  ll res = power(x, n / 2);
  if (n % 2 == 0)
    return res * res;
  else
    return res * res * x;
}

int getl(int i, int N) { return i == 0 ? N - 1 : i - 1; };
int getr(int i, int N) { return i == N - 1 ? 0 : i + 1; };

/* <--------------------------------------------> */

int n, k;
// 市松模様は[0,2k)*[0,2k)のどこを黒い部分の左下にするかという情報で一意に定まる（全単射）ので、そのように表す
// imos[i][j] :=
// (i,j)が黒い部分の左下になるような市松模様を塗った時に叶えられる希望の数
vector<vector<int>> imos(2020, vector<int>(2020, 0));

// (x,y)∈[x-k+1, x]*[y-k+1,
// y]の範囲でimos[i][j]+=1と累積されるように値をセットする
void set_square(int x, int y) {
  if (x < 0 || y < 0)
    return;
  imos[max(0, x - k + 1)][max(0, y - k + 1)] += 1;
  imos[max(0, x - k + 1)][y + 1] -= 1;
  imos[x + 1][max(0, y - k + 1)] -= 1;
  imos[x + 1][y + 1] += 1;
}

void set_imos(int x, int y, int k, vector<vector<int>> &imos) {
  set_square(x, y);
  set_square(x + k, y - k);
  set_square(x - k, y - k);
  set_square(x + k, y + k);
  set_square(x - k, y + k);
  set_square(x, y + 2 * k);
}

int main() {
  cin >> n >> k;
  // 入力を受け取り、扱いやすいように希望を同値変形して座標を圧縮する
  // 具体的には全ての希望を、「(x,y)∈[0,2k)*[0,2k)を黒に塗りたいな」という希望に同値変形する
  vector<int> x(n), y(n);
  rep(i, 0, n) {
    cin >> x[i] >> y[i];
    char c;
    cin >> c;
    if (c == 'W')
      x[i] += k;
    x[i] %= 2 * k;
    y[i] %= 2 * k;
  }

  rep(i, 0, n) {
    // (x[i],y[i])を黒に塗れるような市松模様(X, Y)について、最後に累積した時に
    // imos[X][Y]+=1 になるように重みを加算する
    set_imos(x[i], y[i], k, imos);
  }

  // 左→右へ累積
  rep(i, 0, 2 * k) rep(j, 1, 2 * k) imos[i][j] += imos[i][j - 1];
  // （問題文の画像で）下→上へ累積
  rep(j, 0, 2 * k) rep(i, 1, 2 * k) imos[i][j] += imos[i - 1][j];

  // 最大値の検索
  int ans = 0;
  rep(i, 0, 2 * k) rep(j, 0, 2 * k) chmax(ans, imos[i][j]);

  cout << ans << '\n';
  return 0;
}


Fixed submission:
#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for (int i = (l); i < (r); ++i)
typedef long long ll;
typedef unsigned long long ull;
template <class T> inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}

/* attention
    long longのシフト演算には気をつけよう
    タイポした時のデバッグが死ぬほどきつくなるので変数名は最低3字くらい使った方がいいかも
    sizeは(int)とキャストしよう
    ごちゃごちゃ場合分けを考える前に全探索は考えましたか？
*/

const ll mod = 1e9 + 7;

void chmod(ll &M) {
  if (M >= mod)
    M %= mod;
  else if (M < 0) {
    M += (abs(M) / mod + 1) * mod;
    M %= mod;
  }
}

ll modpow(ll x, ll n) {
  if (n == 0)
    return 1;

  ll res = modpow(x, n / 2);
  if (n % 2 == 0)
    return res * res % mod;
  else
    return res * res % mod * x % mod;
}

ll power(ll x, ll n) {
  if (n == 0)
    return 1;

  ll res = power(x, n / 2);
  if (n % 2 == 0)
    return res * res;
  else
    return res * res * x;
}

int getl(int i, int N) { return i == 0 ? N - 1 : i - 1; };
int getr(int i, int N) { return i == N - 1 ? 0 : i + 1; };

/* <--------------------------------------------> */

int n, k;
// 市松模様は[0,2k)*[0,2k)のどこを黒い部分の左下にするかという情報で一意に定まる（全単射）ので、そのように表す
// imos[i][j] :=
// (i,j)が黒い部分の左下になるような市松模様を塗った時に叶えられる希望の数
vector<vector<int>> imos(4020, vector<int>(4020, 0));

// (x,y)∈[x-k+1, x]*[y-k+1,
// y]の範囲でimos[i][j]+=1と累積されるように値をセットする
void set_square(int x, int y) {
  if (x < 0 || y < 0)
    return;
  imos[max(0, x - k + 1)][max(0, y - k + 1)] += 1;
  imos[max(0, x - k + 1)][y + 1] -= 1;
  imos[x + 1][max(0, y - k + 1)] -= 1;
  imos[x + 1][y + 1] += 1;
}

void set_imos(int x, int y, int k, vector<vector<int>> &imos) {
  set_square(x, y);
  set_square(x + k, y - k);
  set_square(x - k, y - k);
  set_square(x + k, y + k);
  set_square(x - k, y + k);
  set_square(x, y + 2 * k);
}

int main() {
  cin >> n >> k;
  // 入力を受け取り、扱いやすいように希望を同値変形して座標を圧縮する
  // 具体的には全ての希望を、「(x,y)∈[0,2k)*[0,2k)を黒に塗りたいな」という希望に同値変形する
  vector<int> x(n), y(n);
  rep(i, 0, n) {
    cin >> x[i] >> y[i];
    char c;
    cin >> c;
    if (c == 'W')
      x[i] += k;
    x[i] %= 2 * k;
    y[i] %= 2 * k;
  }

  rep(i, 0, n) {
    // (x[i],y[i])を黒に塗れるような市松模様(X, Y)について、最後に累積した時に
    // imos[X][Y]+=1 になるように重みを加算する
    set_imos(x[i], y[i], k, imos);
  }

  // 左→右へ累積
  rep(i, 0, 2 * k) rep(j, 1, 2 * k) imos[i][j] += imos[i][j - 1];
  // （問題文の画像で）下→上へ累積
  rep(j, 0, 2 * k) rep(i, 1, 2 * k) imos[i][j] += imos[i - 1][j];

  // 最大値の検索
  int ans = 0;
  rep(i, 0, 2 * k) rep(j, 0, 2 * k) chmax(ans, imos[i][j]);

  cout << ans << '\n';
  return 0;
}