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

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

class UnionFindTree {
private:
  vector<int> parent;
  vector<int> count;

public:
  UnionFindTree(int n) : parent(n), count(n, 1) {
    for (int i = 0; i < n; i++)
      parent[i] = i;
  }
  int get_root(const int x) {
    if (parent[x] == x)
      return x;
    return parent[x] = get_root(parent[x]);
  }
  void unite(const int x, const int y) {
    int rx = get_root(x), ry = get_root(y);
    if (rx == ry)
      return;
    parent[rx] = ry;
    count[ry] += count[rx];
    count[rx] = 0;
  }
  bool is_same_root(const int x, const int y) {
    return get_root(x) == get_root(y);
  }
  int get_size(const int x) { return count[get_root(x)]; }
  void print() {
    for (auto elm : parent)
      cout << elm << " ";
    cout << endl;
    for (auto elm : count)
      cout << elm << " ";
    cout << endl;
  }
};
int main() {
  int n;
  cin >> n;
  vector<pair<int, int>> p(n), x(n);
  set<pair<int, int>> y;
  UnionFindTree tree(n);
  for (auto i = 0; i < n; i++) {
    cin >> p[i].first >> p[i].second;
    x[i] = {p[i].first, i};
  }
  sort(x.begin(), x.end());
  for (auto i = 0; i < n; i++) {
    auto tmp = y.lower_bound({p[x[i].second].second, 0});
    for (auto itr = y.begin(); itr != tmp;) {
      tree.unite(x[i].second, itr->second);
      if (itr == y.begin())
        ++itr;
      else
        itr = y.erase(itr);
    }
    if (tmp == y.begin())
      y.insert({p[x[i].second].second, x[i].second});
  }
  for (auto i = 0; i < n; i++)
    cout << tree.get_size(i) << endl;
  return 0;
}

Error: TLE

Fixed submission:

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

class UnionFindTree {
private:
  vector<int> parent;
  vector<int> count;

public:
  UnionFindTree(int n) : parent(n), count(n, 1) {
    // 最初は全てを根として初期化
    for (int i = 0; i < n; i++)
      parent[i] = i;
  }
  int get_root(const int x) {
    // データxが属する木の根を取得する
    if (parent[x] == x)
      return x;
    // 取得したものは直接木の根をつなぐ(経路圧縮)
    return parent[x] = get_root(parent[x]);
  }
  void unite(const int x, const int y) {
    // xとyの木を併合する
    int rx = get_root(x);
    int ry = get_root(y);
    // 元から同じ木に属している場合は何もしない
    if (rx == ry)
      return;
    // xの属する木をyの属する木につける
    parent[rx] = ry;
    count[ry] += count[rx];
    count[rx] = 0;
  }
  bool is_same_root(const int x, const int y) {
    return get_root(x) == get_root(y);
  }
  int get_size(const int x) { return count[get_root(x)]; }
  void print() {
    for (auto elm : parent)
      cout << elm << " ";
    cout << endl;
    for (auto elm : count)
      cout << elm << " ";
    cout << endl;
  }
};
int main() {
  int n;
  cin >> n;
  vector<pair<int, int>> p(n), x(n), y(n);
  UnionFindTree tree(n);
  for (auto i = 0; i < n; i++) {
    cin >> p[i].first >> p[i].second;
    x[i] = {p[i].first, i}, y[i] = {p[i].second, i};
  }
  sort(x.begin(), x.end());
  sort(y.begin(), y.end());
  for (auto i = 0; i < n; i++) {
    auto itr =
        lower_bound(y.begin(), y.end(), make_pair(p[x[i].second].second, 0));
    for (auto j = itr; j != y.end(); j++) {
      if (x[i].first < p[j->second].first)
        tree.unite(x[i].second, j->second);
    }
  }
  for (auto i = 0; i < n; i++)
    cout << tree.get_size(i) << endl;
  return 0;
}