Problem p03236 (C++)

Buggy submission (status: Time Limit Exceeded):
// 無理。

#include <bits/stdc++.h>

using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;

const int MN = 1550;
int N;
using B = array<ull, MN / 64 + 1>;
int g[MN][MN];

B used[MN][MN];

namespace std {
bool operator<(const B &l, const B &r) {
  for (int i = 0; i < MN / 64 + 1; i++) {
    if (l[i] != r[i])
      return l[i] < r[i];
  }
  return false;
}
bool operator>(const B &l, const B &r) { return r < l; }

bool operator==(const B &l, const B &r) {
  for (int i = 0; i < MN / 64 + 1; i++) {
    if (l[i] != r[i])
      return false;
  }
  return true;
}
} // namespace std

bool sam(const B &l, const B &r) {
  for (int i = 0; i < MN / 64 + 1; i++) {
    if (l[i] & r[i])
      return true;
  }
  return false;
}

bool gt(const B &b, int id) { return (b[id / 64] & (1ULL << (id % 64))) != 0; }

void st(B &b, int id) { b[id / 64] |= 1ULL << (id % 64); }

int L, R, D, U;
void dfs_up(int a, int b, int id) {
  if (!(L <= a && a <= R && D <= b && b <= U))
    return;
  // if (g[a][b] == 0 || used[a][b][id]) return;
  if (g[a][b] == 0 || gt(used[a][b], id))
    return;
  st(used[a][b], id);
  // used[a][b][id] = true;
  dfs_up(a - 1, b, id);
  dfs_up(a, b - 1, id);
}

void dfs_dw(int a, int b, int id) {
  if (!(L <= a && a <= R && D <= b && b <= U))
    return;
  if (g[a][b] == 0 || gt(used[a][b], id))
    return;
  st(used[a][b], id);
  //    if (g[a][b] == 0 || used[a][b][id]) return;
  //    used[a][b][id] = true;
  dfs_dw(a + 1, b, id);
  dfs_dw(a, b + 1, id);
}

ll ans = 0;

using P = pair<B, int>;

V<P> uni(V<P> v) {
  sort(v.begin(), v.end());
  V<P> res;
  for (auto &p : v) {
    if (res.size() && res.back().first == p.first) {
      res.back().second += p.second;
      continue;
    }
    res.push_back(p);
  }
  return res;
}
void solve(int l, int r, int d, int u) {
  if (r < l || u < d)
    return;
  if (l == r && d == u)
    return;
  L = l;
  R = r;
  D = d;
  U = u;
  for (int x = l; x <= r; x++) {
    for (int y = d; y <= u; y++) {
      used[x][y] = B();
    }
  }
  if (r - l > u - d) {
    int m = (l + r) / 2;
    for (int y = d; y <= u; y++) {
      dfs_up(m, y, y);
    }
    for (int y = u; y >= d; y--) {
      dfs_dw(m + 1, y, y);
    }
    V<P> mp1, mp2;
    for (int x = l; x <= r; x++) {
      for (int y = d; y <= u; y++) {
        if (x <= m)
          mp1.push_back(P(used[x][y], g[x][y]));
        else
          mp2.push_back(P(used[x][y], g[x][y]));
      }
    }
    mp1 = uni(mp1);
    mp2 = uni(mp2);

    for (auto &p1 : mp1) {
      for (auto &p2 : mp2) {
        // if ((p1.first & p2.first).count()) ans += ll(p1.second) * p2.second;
        if (sam(p1.first, p2.first))
          ans += ll(p1.second) * p2.second;
      }
    }
    solve(l, m, d, u);
    solve(m + 1, r, d, u);
  } else {
    int m = (d + u) / 2;

    for (int x = l; x <= r; x++) {
      dfs_up(x, m, x);
    }
    for (int x = r; x >= l; x--) {
      dfs_dw(x, m + 1, x);
    }

    using P = pair<B, int>;
    V<P> mp1, mp2;
    for (int x = l; x <= r; x++) {
      for (int y = d; y <= u; y++) {
        if (y <= m)
          mp1.push_back(P(used[x][y], g[x][y]));
        else
          mp2.push_back(P(used[x][y], g[x][y]));
      }
    }
    mp1 = uni(mp1);
    mp2 = uni(mp2);
    /*        map<B, int> mp1, mp2;
            for (int x = l; x <= r; x++) {
                for (int y = d; y <= u; y++) {
                    if (y <= m) mp1[used[x][y]] += g[x][y];
                    else mp2[used[x][y]] += g[x][y];
                }
            }*/
    for (auto &p1 : mp1) {
      for (auto &p2 : mp2) {
        if (sam(p1.first, p2.first))
          ans += ll(p1.second) * p2.second;
      }
    }
    solve(l, r, d, m);
    solve(l, r, m + 1, u);
  }
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout << setprecision(20) << fixed;
  cin >> N;
  for (int i = 1; i <= N; i++) {
    string s;
    cin >> s;
    for (int j = 1; j <= N; j++) {
      int d = 0;
      if (isdigit(s[j - 1]))
        d = s[j - 1] - '0';
      g[i][j] = d;
      // ans -= d*d;
    }
  }
  solve(1, N, 1, N);
  cout << ans << endl;
  return 0;
}


Fixed submission:
// 無理。

#include <bits/stdc++.h>

using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }
template <class T> using V = vector<T>;
template <class T> using VV = V<V<T>>;

const int MN = 550;
int N;
using B = array<ull, MN / 64 + 1>;
int g[MN][MN];

B used[MN][MN];

namespace std {
bool operator<(const B &l, const B &r) {
  for (int i = 0; i < MN / 64 + 1; i++) {
    if (l[i] != r[i])
      return l[i] < r[i];
  }
  return false;
}
bool operator>(const B &l, const B &r) { return r < l; }

bool operator==(const B &l, const B &r) {
  for (int i = 0; i < MN / 64 + 1; i++) {
    if (l[i] != r[i])
      return false;
  }
  return true;
}
} // namespace std

bool sam(const B &l, const B &r) {
  for (int i = 0; i < MN / 64 + 1; i++) {
    if (l[i] & r[i])
      return true;
  }
  return false;
}

bool gt(const B &b, int id) { return (b[id / 64] & (1ULL << (id % 64))) != 0; }

void st(B &b, int id) { b[id / 64] |= 1ULL << (id % 64); }

int L, R, D, U;
void dfs_up(int a, int b, int id) {
  if (!(L <= a && a <= R && D <= b && b <= U))
    return;
  // if (g[a][b] == 0 || used[a][b][id]) return;
  if (g[a][b] == 0 || gt(used[a][b], id))
    return;
  st(used[a][b], id);
  // used[a][b][id] = true;
  dfs_up(a - 1, b, id);
  dfs_up(a, b - 1, id);
}

void dfs_dw(int a, int b, int id) {
  if (!(L <= a && a <= R && D <= b && b <= U))
    return;
  if (g[a][b] == 0 || gt(used[a][b], id))
    return;
  st(used[a][b], id);
  //    if (g[a][b] == 0 || used[a][b][id]) return;
  //    used[a][b][id] = true;
  dfs_dw(a + 1, b, id);
  dfs_dw(a, b + 1, id);
}

ll ans = 0;

using P = pair<B, int>;

V<P> uni(V<P> v) {
  sort(v.begin(), v.end());
  V<P> res;
  for (auto &p : v) {
    if (res.size() && res.back().first == p.first) {
      res.back().second += p.second;
      continue;
    }
    res.push_back(p);
  }
  return res;
}
void solve(int l, int r, int d, int u) {
  if (r < l || u < d)
    return;
  if (l == r && d == u)
    return;
  L = l;
  R = r;
  D = d;
  U = u;
  for (int x = l; x <= r; x++) {
    for (int y = d; y <= u; y++) {
      used[x][y] = B();
    }
  }
  if (r - l > u - d) {
    int m = (l + r) / 2;
    for (int y = d; y <= u; y++) {
      dfs_up(m, y, y);
    }
    for (int y = u; y >= d; y--) {
      dfs_dw(m + 1, y, y);
    }
    V<P> mp1, mp2;
    for (int x = l; x <= r; x++) {
      for (int y = d; y <= u; y++) {
        if (x <= m)
          mp1.push_back(P(used[x][y], g[x][y]));
        else
          mp2.push_back(P(used[x][y], g[x][y]));
      }
    }
    mp1 = uni(mp1);
    mp2 = uni(mp2);

    for (auto &p1 : mp1) {
      for (auto &p2 : mp2) {
        // if ((p1.first & p2.first).count()) ans += ll(p1.second) * p2.second;
        if (sam(p1.first, p2.first))
          ans += ll(p1.second) * p2.second;
      }
    }
    solve(l, m, d, u);
    solve(m + 1, r, d, u);
  } else {
    int m = (d + u) / 2;

    for (int x = l; x <= r; x++) {
      dfs_up(x, m, x);
    }
    for (int x = r; x >= l; x--) {
      dfs_dw(x, m + 1, x);
    }

    using P = pair<B, int>;
    V<P> mp1, mp2;
    for (int x = l; x <= r; x++) {
      for (int y = d; y <= u; y++) {
        if (y <= m)
          mp1.push_back(P(used[x][y], g[x][y]));
        else
          mp2.push_back(P(used[x][y], g[x][y]));
      }
    }
    mp1 = uni(mp1);
    mp2 = uni(mp2);
    /*        map<B, int> mp1, mp2;
            for (int x = l; x <= r; x++) {
                for (int y = d; y <= u; y++) {
                    if (y <= m) mp1[used[x][y]] += g[x][y];
                    else mp2[used[x][y]] += g[x][y];
                }
            }*/
    for (auto &p1 : mp1) {
      for (auto &p2 : mp2) {
        if (sam(p1.first, p2.first))
          ans += ll(p1.second) * p2.second;
      }
    }
    solve(l, r, d, m);
    solve(l, r, m + 1, u);
  }
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout << setprecision(20) << fixed;
  cin >> N;
  for (int i = 1; i <= N; i++) {
    string s;
    cin >> s;
    for (int j = 1; j <= N; j++) {
      int d = 0;
      if (isdigit(s[j - 1]))
        d = s[j - 1] - '0';
      g[i][j] = d;
      // ans -= d*d;
    }
  }
  solve(1, N, 1, N);
  cout << ans << endl;
  return 0;
}