Problem p00541 (C++)

Buggy submission (status: Memory Limit Exceeded):
#include <bits/stdc++.h>
using namespace std;

const int maxn = (int)4004;

int H, W, L, P;
int a[maxn][maxn];
int _up[maxn][maxn], _down[maxn][maxn], _left[maxn][maxn], _right[maxn][maxn];
long long res;
int BIT[maxn][2];

int get(int id, int x) {
  int ret = 0;
  while (x > 0) {
    ret += BIT[x][id];
    x -= x & (-x);
  }
  return ret;
}
void upd(int id, int x, int val) {
  while (x < maxn) {
    BIT[x][id] += val;
    x += x & (-x);
  }
}
void update(int id, int x, int y, int val) {
  if (x > y)
    return;
  upd(id, x, val);
  upd(id, y + 1, -val);
}

void solve(int _x, int _y) {
  for (int i = 0; i < maxn; i++)
    BIT[i][0] = BIT[i][1] = 0;
  int x = _x, y = _y;
  vector<pair<int, pair<int, int>>> V;
  while (x <= H && y <= W) {
    V.push_back(make_pair(min(_left[x][y], _up[x][y]), make_pair(1, x)));
    V.push_back(make_pair(min(_right[x][y], _down[x][y]), make_pair(0, x)));
    x++;
    y++;
  }
  sort(V.begin(), V.end());

  for (int i = 0; i < V.size(); i++) {
    int sz = V[i].first;
    int type = V[i].second.first;
    int pos = V[i].second.second;
    /// cout << sz << ' ' << pos << ' ' << type << endl;
    if (type == 1) {
      res += get(1, pos);
      update(0, pos - sz + 1, pos - L, 1);
    } else {
      res += get(0, pos);
      update(1, pos + L, pos + sz - 1, 1);
    }
  }
}

int main() {
  /// freopen("test.txt", "r", stdin);
  ios_base::sync_with_stdio(0);

  cin >> H >> W >> L >> P;
  L--;
  while (P--) {
    int x, y;
    cin >> x >> y;
    a[x][y] = 1;
  }

  for (int i = 1; i <= H; i++) {
    for (int j = 1; j <= W; j++) {
      _up[i][j] = (a[i][j] ? 0 : _up[i - 1][j] + 1);
      _left[i][j] = (a[i][j] ? 0 : _left[i][j - 1] + 1);
    }
  }

  for (int i = H; i >= 1; i--) {
    for (int j = W; j >= 1; j--) {
      _down[i][j] = (a[i][j] ? 0 : _down[i + 1][j] + 1);
      _right[i][j] = (a[i][j] ? 0 : _right[i][j + 1] + 1);
    }
  }
  /// solve(2, 1);
  for (int i = 1; i <= H; i++)
    solve(i, 1);
  for (int i = 2; i <= W; i++)
    solve(1, i);
  cout << res << endl;
}

Fixed submission:
#include <bits/stdc++.h>
using namespace std;

const int maxn = (int)4004;

int H, W, L, P;
bool a[maxn][maxn];
short _up[maxn][maxn], _down[maxn][maxn], _left[maxn][maxn], _right[maxn][maxn];
long long res;
int BIT[maxn][2];

int get(int id, int x) {
  int ret = 0;
  while (x > 0) {
    ret += BIT[x][id];
    x -= x & (-x);
  }
  return ret;
}
void upd(int id, int x, int val) {
  while (x < maxn) {
    BIT[x][id] += val;
    x += x & (-x);
  }
}
void update(int id, int x, int y, int val) {
  if (x > y)
    return;
  upd(id, x, val);
  upd(id, y + 1, -val);
}

void solve(int _x, int _y) {
  for (int i = 0; i < maxn; i++)
    BIT[i][0] = BIT[i][1] = 0;
  int x = _x, y = _y;
  vector<pair<int, pair<int, int>>> V;
  while (x <= H && y <= W) {
    V.push_back(make_pair(min(_left[x][y], _up[x][y]), make_pair(1, x)));
    V.push_back(make_pair(min(_right[x][y], _down[x][y]), make_pair(0, x)));
    x++;
    y++;
  }
  sort(V.begin(), V.end());

  for (int i = 0; i < V.size(); i++) {
    int sz = V[i].first;
    int type = V[i].second.first;
    int pos = V[i].second.second;
    /// cout << sz << ' ' << pos << ' ' << type << endl;
    if (type == 1) {
      res += get(1, pos);
      update(0, pos - sz + 1, pos - L, 1);
    } else {
      res += get(0, pos);
      update(1, pos + L, pos + sz - 1, 1);
    }
  }
}

int main() {
  /// freopen("test.txt", "r", stdin);
  ios_base::sync_with_stdio(0);

  cin >> H >> W >> L >> P;
  L--;
  while (P--) {
    int x, y;
    cin >> x >> y;
    a[x][y] = 1;
  }

  for (int i = 1; i <= H; i++) {
    for (int j = 1; j <= W; j++) {
      _up[i][j] = (a[i][j] ? 0 : _up[i - 1][j] + 1);
      _left[i][j] = (a[i][j] ? 0 : _left[i][j - 1] + 1);
    }
  }

  for (int i = H; i >= 1; i--) {
    for (int j = W; j >= 1; j--) {
      _down[i][j] = (a[i][j] ? 0 : _down[i + 1][j] + 1);
      _right[i][j] = (a[i][j] ? 0 : _right[i][j + 1] + 1);
    }
  }
  /// solve(2, 1);
  for (int i = 1; i <= H; i++)
    solve(i, 1);
  for (int i = 2; i <= W; i++)
    solve(1, i);
  cout << res << endl;
}