Problem p01427 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>

using namespace std;
#define rep(i, n) for (int i = 0; i < n; i++)

bool comp2(pair<pair<int, int>, int> a, pair<pair<int, int>, int> b) {
  int x = a.first.first;
  int y = a.first.second;
  int w = b.first.first;
  int z = b.first.second;
  if (x * z == y * w) {
    return 1;
  }
  if (x * z > y * w) {
    return 0;
  }
  if (x * z < y * w) {
    return 0;
  }
}

bool comp(pair<pair<int, int>, int> a, pair<pair<int, int>, int> b) {
  int x = a.first.first;
  int y = a.first.second;
  int w = b.first.first;
  int z = b.first.second;
  if (x * z == y * w) {
    return 0;
  }
  if (x * z > y * w) {
    return 1;
  }
  if (x * z < y * w) {
    return 0;
  }
}

int main() {
  int h, w;
  cin >> h >> w;
  vector<string> v(h);
  rep(i, h) cin >> v[h - i - 1];
  rep(i, h) v[i].push_back('.');
  rep(i, h) v[i] = "." + v[i];
  string ssss;
  rep(i, w + 2) ssss.push_back('.');
  v.push_back(ssss);
  vector<pair<pair<int, int>, int>> p;
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w + 1; j++) {
      if (v[i][j] == '#' && v[i][j + 1] == '#' && v[i + 1][j] == '.' &&
          v[i + 1][j + 1] == '#') {
        p.push_back(make_pair(make_pair(i + 1, j), -1));
      }
      if (v[i][j] == '.' && v[i][j + 1] == '.' && v[i + 1][j] == '#' &&
          v[i + 1][j + 1] == '.') {
        p.push_back(make_pair(make_pair(i + 1, j), -1));
      }
      if (v[i][j] == '#' && v[i][j + 1] == '.' && v[i + 1][j] == '#' &&
          v[i + 1][j + 1] == '#') {
        p.push_back(make_pair(make_pair(i + 1, j), 1));
      }
      if (v[i][j] == '.' && v[i][j + 1] == '#' && v[i + 1][j] == '.' &&
          v[i + 1][j + 1] == '.') {
        p.push_back(make_pair(make_pair(i + 1, j), 1));
      }
    }
  }
  sort(p.begin(), p.end(), comp);
  int mx = 2;
  int cnt = 1;
  // rep(i,h+1){
  //     rep(j,w+2){
  //         cout << v[i][j];
  //     }
  //     cout <<endl;
  // }
  for (int i = 0; i < p.size(); i++) {
    // cout << p[i].first.first << " " << p[i].first.second << " " <<
    // p[i].second << " " << cnt<< endl;
    if (i == p.size() - 1) {
      cnt += p[i].second;
      mx = max(mx, cnt);
    } else {
      if (!comp2(p[i], p[i + 1])) {
        cnt += p[i].second;
        mx = max(mx, cnt);
      } else {
        cnt += p[i].second;
      }
    }
  }
  cout << mx << endl;
  return 0;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <iostream>
#include <set>
#include <string>
#include <utility>
#include <vector>
using namespace std;
#define rep(i, n) for (int i = 0; i < n; i++)
class UF {
private:
  int sz;
  vector<int> par, nrank, size;

public:
  UF() {}
  UF(int node_size) {
    sz = node_size;
    par.resize(sz), nrank.resize(sz), size.resize(sz);
    rep(i, sz) {
      par[i] = i;
      nrank[i] = 0;
      size[i] = 1;
    }
  }
  int find(int x) {
    if (par[x] == x) {
      return x;
    } else {
      return par[x] = find(par[x]);
    }
  }
  void unite(int x, int y) {
    x = find(x), y = find(y);
    if (x == y)
      return;
    if (nrank[x] < nrank[y])
      swap(x, y);
    par[y] = x;
    size[x] += size[y];
    if (nrank[x] == nrank[y])
      nrank[x]++;
  }
  int query(int x) {
    x = find(x);
    return size[x];
  }
  bool same(int x, int y) { return find(x) == find(y); }
};

int main() {
  int n, m;
  cin >> n >> m;
  vector<string> s(n);
  rep(i, n) cin >> s[n - 1 - i];
  vector<vector<bool>> p(n + 1, vector<bool>(m + 1));
  vector<vector<bool>> pp(n + 1, vector<bool>(m + 1));
  vector<vector<bool>> qq(n + 1, vector<bool>(m + 1));
  vector<vector<bool>> used(2 * (n + 1), vector<bool>(2 * (m + 1)));
  set<pair<int, int>> v;
  for (int i = 1; i < n; i++) {
    for (int j = 1; j < m; j++) {
      if (s[i - 1][j - 1] == '#' && s[i][j - 1] == '#' && s[i - 1][j] == '#' &&
          s[i][j] == '#') {
        continue;
      }
      if (s[i - 1][j - 1] == '.' && s[i][j - 1] == '.' && s[i - 1][j] == '.' &&
          s[i][j] == '.') {
        continue;
      }
      v.insert(make_pair(2 * i, 2 * j));
      v.insert(make_pair(2 * i - 1, 2 * j));
      v.insert(make_pair(2 * i + 1, 2 * j));
      v.insert(make_pair(2 * i - 1, 2 * j - 1));
      v.insert(make_pair(2 * i + 1, 2 * j + 1));
      v.insert(make_pair(2 * i - 1, 2 * j + 1));
      v.insert(make_pair(2 * i + 1, 2 * j - 1));
      v.insert(make_pair(2 * i, 2 * j - 1));
      v.insert(make_pair(2 * i, 2 * j + 1));
    }
  }
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      if (s[i][j] == '#') {
        p[i][j] = 1;
        p[i + 1][j] = 1;
        p[i][j + 1] = 1;
        p[i + 1][j + 1] = 1;
        pp[i][j] = 1;
        pp[i + 1][j] = 1;
        qq[i][j] = 1;
        qq[i][j + 1] = 1;
      }
    }
  }
  int ma = 2;
  int ng = (n + 1) * (m + 1);
  used[0][0] = 1;
  for (auto x : v) {
    int a = x.first;
    int b = x.second;
    if (used[a][b])
      continue;
    for (int i = 1; i < 1000; i++) {
      if (a * i > n || b * i > m)
        break;
      used[a * i][b * i] = 1;
    }
    UF v((n + 1) * (m + 1) + 1);
    vector<vector<int>> d(n + 1, vector<int>(m + 1));
    for (int i = 0; i < n + 1; i++) {
      for (int j = 0; j < m + 1; j++) {
        if (!p[i][j]) {
          d[i][j] = -1;
        } else if (a * j == i * b) {
          d[i][j] = 0;
        } else if (a * j > i * b) {
          d[i][j] = 1;
        } else {
          d[i][j] = 2;
        }
      }
    }
    for (int i = 0; i < n + 1; i++) {
      for (int j = 0; j < m + 1; j++) {
        int now = i * (m + 1) + j;
        if (d[i][j] == -1) {
          v.unite(now, ng);
        } else if (d[i][j] == 0) {
          v.unite(now, ng);
          if (i > 0 && j < m) {
            if (qq[i - 1][j] && pp[i][j]) {
              v.unite(now - m - 1, now + 1);
            }
          }
          if (i < n && j > 0) {
            if (qq[i][j] && pp[i][j - 1]) {
              v.unite(now + m + 1, now - 1);
            }
          }
        } else {
          if (i + 1 < n + 1) {
            if (d[i][j] == d[i + 1][j] && (qq[i][j])) {
              v.unite(now, now + m + 1);
            }
          }
          if (j + 1 < m + 1) {
            if (d[i][j] == d[i][j + 1] && (pp[i][j])) {
              v.unite(now, now + 1);
            }
          }
        }
      }
    }
    set<int> st;
    for (int i = 0; i < n + 1; i++) {
      for (int j = 0; j < m + 1; j++) {
        int now = i * (m + 1) + j;
        if (!v.same(now, ng)) {
          st.insert(v.find(now));
        }
      }
    }
    // cout << "a=" << a << "b=" << b << endl;
    // for(auto x:st){
    //     cout << x/(m+1) << " " << x%(m+1) << endl;
    // }
    ma = max(ma, (int)st.size());
  }
  cout << ma << endl;
  return 0;
}