Problem p03630 (C++)

Buggy submission (status: Time Limit Exceeded):
#include <bits/stdc++.h>
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define per(i, a, b) for (int i = (a); i >= (b); --i)
#define pb push_back
#define mp make_pair
#define pr pair<int, int>
#define x first
#define y second
using namespace std;

template <typename T> void read(T &n) {
  char ch;
  int sign = 1;
  while (!isdigit(ch = getchar()))
    if (ch == '-')
      sign = -1;
  n = ch - '0';
  while (isdigit(ch = getchar()))
    n = n * 10 + ch - '0';
  n *= sign;
}
typedef long long ll;
const int INF = 1e9 + 7;
const int N = 2111;
int n, m, head, tail;
int a[N][N], vis[N][N], up[N][N], prv[N], suf[N], que[N];

int main() {
  freopen("test.in", "r", stdin);
  freopen("test.out", "w", stdout);
  read(n), read(m);
  rep(i, 1, n) rep(j, 1, m) {
    char opt;
    scanf(" %c", &opt);
    a[i][j] = opt == '.' ? 0 : 1;
  }
  rep(i, 1, n - 1) rep(j, 1, m - 1) {
    int sum = a[i][j] + a[i + 1][j] + a[i][j + 1] + a[i + 1][j + 1];
    if (sum % 2)
      vis[i + 1][j + 1] = 1;
  }
  rep(j, 1, m + 1) rep(i, 2, n + 1) up[i][j] =
      vis[i - 1][j] ? 1 : up[i - 1][j] + 1;
  rep(i, 1, n + 1) up[i][1] = up[i][m + 1] = 0;
  int ans = 0;
  rep(i, 1, n + 1) {
    memset(prv, 0, sizeof(prv)), memset(suf, 0, sizeof(suf));
    head = tail = 1, que[1] = 1;
    rep(j, 1, m + 1) {
      int l = head, r = tail + 1;
      while (l + 1 < r) {
        int mid = (l + r) >> 1;
        if (up[i][que[mid]] < up[i][j])
          l = mid;
        else
          r = mid;
      }
      prv[j] = que[l];
      while (head <= tail && up[i][que[tail]] >= up[i][j])
        tail--;
      que[++tail] = j;
    }
    head = tail = 1, que[1] = m + 1;
    per(j, m + 1, 1) {
      int l = head, r = tail + 1;
      while (l + 1 < r) {
        int mid = (l + r) >> 1;
        if (up[i][que[mid]] < up[i][j])
          l = mid;
        else
          r = mid;
      }
      suf[j] = que[l];
      while (head <= tail && up[i][que[tail]] >= up[i][j])
        tail--;
      que[++tail] = j;
    }
    rep(j, 1, m + 1) ans = max(ans, up[i][j] * (suf[j] - prv[j]));
  }
  printf("%d\n", max(ans, max(n, m)));
  return 0;
}

Fixed submission:
#include <bits/stdc++.h>
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define per(i, a, b) for (int i = (a); i >= (b); --i)
#define pb push_back
#define mp make_pair
#define pr pair<int, int>
#define x first
#define y second
using namespace std;

template <typename T> void read(T &n) {
  char ch;
  int sign = 1;
  while (!isdigit(ch = getchar()))
    if (ch == '-')
      sign = -1;
  n = ch - '0';
  while (isdigit(ch = getchar()))
    n = n * 10 + ch - '0';
  n *= sign;
}
typedef long long ll;
const int INF = 1e9 + 7;
const int N = 2111;
int n, m, head, tail;
int a[N][N], vis[N][N], up[N][N], prv[N], suf[N], que[N];

int main() {
  read(n), read(m);
  rep(i, 1, n) rep(j, 1, m) {
    char opt;
    scanf(" %c", &opt);
    a[i][j] = opt == '.' ? 0 : 1;
  }
  rep(i, 1, n - 1) rep(j, 1, m - 1) {
    int sum = a[i][j] + a[i + 1][j] + a[i][j + 1] + a[i + 1][j + 1];
    if (sum % 2)
      vis[i + 1][j + 1] = 1;
  }
  rep(j, 1, m + 1) rep(i, 2, n + 1) up[i][j] =
      vis[i - 1][j] ? 1 : up[i - 1][j] + 1;
  rep(i, 1, n + 1) up[i][1] = up[i][m + 1] = 0;
  int ans = 0;
  rep(i, 1, n + 1) {
    memset(prv, 0, sizeof(prv)), memset(suf, 0, sizeof(suf));
    head = tail = 1, que[1] = 1;
    rep(j, 1, m + 1) {
      int l = head, r = tail + 1;
      while (l + 1 < r) {
        int mid = (l + r) >> 1;
        if (up[i][que[mid]] < up[i][j])
          l = mid;
        else
          r = mid;
      }
      prv[j] = que[l];
      while (head <= tail && up[i][que[tail]] >= up[i][j])
        tail--;
      que[++tail] = j;
    }
    head = tail = 1, que[1] = m + 1;
    per(j, m + 1, 1) {
      int l = head, r = tail + 1;
      while (l + 1 < r) {
        int mid = (l + r) >> 1;
        if (up[i][que[mid]] < up[i][j])
          l = mid;
        else
          r = mid;
      }
      suf[j] = que[l];
      while (head <= tail && up[i][que[tail]] >= up[i][j])
        tail--;
      que[++tail] = j;
    }
    rep(j, 1, m + 1) ans = max(ans, up[i][j] * (suf[j] - prv[j]));
  }
  printf("%d\n", max(ans, max(n, m)));
  return 0;
}