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

#include <bits/stdc++.h>
// #include <atcoder/all>
using namespace std;
// using namespace atcoder;
#define int long long

struct UnionFind {
  vector<int> par;
  vector<int> siz;

  UnionFind(int n) : par(n), siz(n) {
    for (int i = 0; i < n; i++) {
      par[i] = i;
      siz[i] = 1;
    }
  }

  int root(int x) {
    if (par[x] == x)
      return x;
    else
      return par[x] = root(par[x]);
  }

  int size(int x) { return siz[root(x)]; }

  void unite(int x, int y) {
    int rx = root(x);
    int ry = root(y);
    if (rx != ry) {
      par[ry] = rx;
      siz[rx] += siz[ry];
    }
  }

  bool same(int x, int y) { return root(x) == root(y); }
};

signed main() {
  // cout << fixed << setprecision(10) << flush;

  int n;
  cin >> n;

  vector<int> x(n), y(n);
  for (int i = 0; i < n; i++) {
    cin >> x[i] >> y[i];
  }

  vector<int> inv_x(n + 1), inv_y(n + 1);
  for (int i = 0; i < n; i++) {
    inv_x[x[i]] = i;
    inv_y[y[i]] = i;
  }

  sort(x.begin(), x.end());

  UnionFind uf(n);
  set<pair<int, int>> st;
  for (int i = 0; i < x.size(); i++) {
    auto itr_lim = st.lower_bound(make_pair(y[inv_x[x[i]]], inv_x[x[i]]));
    bool f = true;
    for (auto itr = st.begin(); itr != itr_lim; itr++) {
      uf.unite(inv_x[x[i]], itr->second);
      f = false;
    }

    if (f)
      st.insert(make_pair(y[inv_x[x[i]]], inv_x[x[i]]));
  }

  for (int i = 0; i < n; i++) {
    cout << uf.size(i) << endl;
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <bits/stdc++.h>
// #include <atcoder/all>
using namespace std;
// using namespace atcoder;
#define int long long

struct UnionFind {
  vector<int> par;
  vector<int> siz;

  UnionFind(int n) : par(n), siz(n) {
    for (int i = 0; i < n; i++) {
      par[i] = i;
      siz[i] = 1;
    }
  }

  int root(int x) {
    if (par[x] == x)
      return x;
    else
      return par[x] = root(par[x]);
  }

  int size(int x) { return siz[root(x)]; }

  void unite(int x, int y) {
    int rx = root(x);
    int ry = root(y);
    if (rx != ry) {
      par[ry] = rx;
      siz[rx] += siz[ry];
    }
  }

  bool same(int x, int y) { return root(x) == root(y); }
};

signed main() {
  // cout << fixed << setprecision(10) << flush;

  int n;
  cin >> n;

  vector<int> x(n), y(n);
  for (int i = 0; i < n; i++) {
    cin >> x[i] >> y[i];
  }

  vector<int> inv_x(n + 1), inv_y(n + 1);
  for (int i = 0; i < n; i++) {
    inv_x[x[i]] = i;
    inv_y[y[i]] = i;
  }

  sort(x.begin(), x.end());

  UnionFind uf(n);
  set<pair<int, int>> st;
  for (int i = 0; i < x.size(); i++) {
    auto itr_lim = st.lower_bound(make_pair(y[inv_x[x[i]]], inv_x[x[i]]));
    for (auto itr = st.begin(); itr != itr_lim; itr++) {
      uf.unite(inv_x[x[i]], itr->second);
    }
    auto itr_lim2 = itr_lim;
    if (itr_lim->first != st.begin()->first) {
      itr_lim--;
      int y_prev = y[inv_x[x[i]]];
      bool flag = true;
      while (flag) {
        if (itr_lim->first + 1 == y_prev) {
          auto itr_del = itr_lim;
          y_prev--;
          // cout << itr_lim->first << endl;
          // cout << st.begin()->first << endl;
          if (itr_lim->first == st.begin()->first)
            flag = false;
          else
            itr_lim--;
          st.erase(itr_del);
        } else
          break;
      }
    }

    if (itr_lim2 != st.end()) {
      int y_prev = y[inv_x[x[i]]];
      bool flag = true;
      itr_lim2++;
      while (itr_lim2 != st.end()) {
        if (itr_lim2->first == y_prev + 1) {
          auto itr_del = itr_lim2;
          y_prev++;
          itr_lim++;
          st.erase(itr_del);
        } else
          break;
      }
    }

    st.insert(make_pair(y[inv_x[x[i]]], inv_x[x[i]]));
  }

  for (int i = 0; i < n; i++) {
    cout << uf.size(i) << endl;
  }

  return 0;
}