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

#include <algorithm>
#include <chrono>
#include <cmath>
#include <deque>
#include <fstream>
#include <functional>
#include <iostream>
#include <iterator>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#define forr(i, start, count) for (int i = (start); i < (start) + (count); ++i)
#define set_map_includes(set, elt) (set.find((elt)) != set.end())
#define readint(i)                                                             \\
  int i;                                                                       \\
  cin >> i
#define readll(i)                                                              \\
  ll i;                                                                        \\
  cin >> i
#define readdouble(i)                                                          \\
  double i;                                                                    \\
  cin >> i
#define readstring(s)                                                          \\
  string s;                                                                    \\
  cin >> s

typedef long long ll;

using namespace std;

ll modd = 1000 * 1000 * 1000 + 7;

class UnionFind {
public:
  vector<int> parent;
  vector<int> size;
  //      size[i] = number of nodes in tree rooted at i
  // Note: not necessarily correct if i is not a root node
  set<int> roots;

  UnionFind(int n) : parent(n), size(n) {
    forr(i, 0, n) { roots.insert(i); }
    forr(i, 0, n) {
      parent[i] = i;
      size[i] = 1;
    }
  }

  int Find(int p) {
    int root = p;
    while (root != parent[root]) {
      root = parent[root];
    }
    while (p != root) {
      int newp = parent[p];
      parent[p] = root;
      p = newp;
    }
    return root;
  }

  void Union(int p, int q) {
    int rootP = Find(p);
    int rootQ = Find(q);
    if (rootP == rootQ)
      return;

    if (size[rootP] < size[rootQ]) {
      parent[rootP] = rootQ;
      size[rootQ] += size[rootP];
      roots.erase(rootP);
    } else {
      parent[rootQ] = rootP;
      size[rootP] += size[rootQ];
      roots.erase(rootQ);
    }
  }
};

int main() {

  ios_base::sync_with_stdio(false);

  cout.precision(17);
  mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
  uniform_int_distribution<int> rand_gen(
      0, modd); // rand_gen(rng) gets the rand no

  //    readint(test_cases);
  int test_cases = 1;
  forr(t, 1, test_cases) {
    readint(n);
    map<int, int> c;
    vector<int> dict;
    forr(i, 0, n) {
      readint(a);
      readint(b);
      c[a] = b;
      dict.push_back(a);
    }
    UnionFind uf(n + 1);
    map<int, int> lowest_y;
    for (auto x : c) {
      bool connected = false;
      for (auto it = lowest_y.begin(); it != lowest_y.end(); ++it) {
        if (it->first < x.second) {
          connected = true;
          int which = it->second;
          uf.Union(which, x.first);
        } else {
          break;
        }
      }
      if (!connected) {
        lowest_y[x.second] = x.first;
      }
    }

    forr(i, 0, n) { cout << uf.size[uf.Find(dict[i])] << endl; }
  }
  return 0;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <chrono>
#include <cmath>
#include <deque>
#include <fstream>
#include <functional>
#include <iostream>
#include <iterator>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#define forr(i, start, count) for (int i = (start); i < (start) + (count); ++i)
#define set_map_includes(set, elt) (set.find((elt)) != set.end())
#define readint(i)                                                             \\
  int i;                                                                       \\
  cin >> i
#define readll(i)                                                              \\
  ll i;                                                                        \\
  cin >> i
#define readdouble(i)                                                          \\
  double i;                                                                    \\
  cin >> i
#define readstring(s)                                                          \\
  string s;                                                                    \\
  cin >> s

typedef long long ll;

using namespace std;

ll modd = 1000 * 1000 * 1000 + 7;

class UnionFind {
public:
  vector<int> parent;
  vector<int> size;
  //      size[i] = number of nodes in tree rooted at i
  // Note: not necessarily correct if i is not a root node
  set<int> roots;

  UnionFind(int n) : parent(n), size(n) {
    forr(i, 0, n) { roots.insert(i); }
    forr(i, 0, n) {
      parent[i] = i;
      size[i] = 1;
    }
  }

  int Find(int p) {
    int root = p;
    while (root != parent[root]) {
      root = parent[root];
    }
    while (p != root) {
      int newp = parent[p];
      parent[p] = root;
      p = newp;
    }
    return root;
  }

  void Union(int p, int q) {
    int rootP = Find(p);
    int rootQ = Find(q);
    if (rootP == rootQ)
      return;

    if (size[rootP] < size[rootQ]) {
      parent[rootP] = rootQ;
      size[rootQ] += size[rootP];
      roots.erase(rootP);
    } else {
      parent[rootQ] = rootP;
      size[rootP] += size[rootQ];
      roots.erase(rootQ);
    }
  }
};

int main() {

  ios_base::sync_with_stdio(false);

  cout.precision(17);
  mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
  uniform_int_distribution<int> rand_gen(
      0, modd); // rand_gen(rng) gets the rand no

  //    readint(test_cases);
  int test_cases = 1;
  forr(t, 1, test_cases) {
    readint(n);
    map<int, int> c;
    vector<int> dict;
    forr(i, 0, n) {
      readint(a);
      readint(b);
      c[a] = b;
      dict.push_back(a);
    }
    UnionFind uf(n + 1);
    map<int, int> lowest_y;
    for (auto x : c) {
      bool connected = false;
      for (auto y : lowest_y) {
        if (y.first < x.second) {
          connected = true;
          int which = y.second;
          uf.Union(which, x.first);
        }
      }
      if (!connected) {
        lowest_y[x.second] = x.first;
      }
    }

    forr(i, 0, n) { cout << uf.size[uf.Find(dict[i])] << endl; }
  }
  return 0;
}