Problem:
Score : 100 points

Problem Statement

You are given an undirected graph with N vertices and 0 edges. Process Q queries of the following types.

0 u v: Add an edge (u, v).

1 u v: Print 1 if u and v are in the same connected component, 0 otherwise.

Constraints

1 \leq N \leq 200,000

1 \leq Q \leq 200,000

0 \leq u_i, v_i \lt N

Input

Input is given from Standard Input in the following format:

N Q
t_1 u_1 v_1
t_2 u_2 v_2
:
t_Q u_Q v_Q

出力

For each query of the latter type, print the answer.

Sample Input 1

4 7
1 0 1
0 0 1
0 2 3
1 0 1
1 1 2
0 0 2
1 1 3

Sample Output 1

0
1
0
1

Solution in C++ (GCC 9.2.1) (judge verdict: Accepted)

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <utility>
#include <cmath>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <map>
#include <tuple>
#include <numeric>
#include <functional>
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vector<ll>> vvl;
typedef pair<ll, ll> P;
#define rep(i, n) for(ll i = 0; i < n; i++)
#define exrep(i, a, b) for(ll i = a; i <= b; i++)
#define out(x) cout << x << endl
#define exout(x) printf("%.10f\n", x)
#define chmax(x, y) x = max(x, y)
#define chmin(x, y) x = min(x, y)
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define pb push_back
#define re0 return 0
const ll mod = 1000000007;
const ll INF = 1e16;
 
class UnionFind {
public:
    vl parent;  // 親ノード
    vl Siz;  // 集合の大きさ
    
    // コンストラクタ
    UnionFind(ll n): parent(n), Siz(n, 1) {
        rep(i, n) {
            parent[i] = i;
        }
    }
 
    // n要素で初期化
    void init(ll n) {
        parent.resize(n);
        Siz.assign(n, 1);
        rep(i, n) {
            parent[i] = i;
        }
    }
 
    // xの属する集合の根を求める
    ll root(ll x) {
        if(parent[x] == x) {
            return x;
        }
        else {
            return parent[x] = root(parent[x]);
        }
    }
 
    // xとyの属する集合を併合
    void unite(ll x, ll y) {
        x = root(x);
        y = root(y);
        if(x == y) {
            return;
        }
        if(Siz[x] < Siz[y]) {
            swap(x, y);
        }
        Siz[x] += Siz[y];
        parent[y] = x;
    }
    
    // xとyが同じ集合に属するかどうか
    bool same(ll x, ll y) {
        return root(x) == root(y);
    }
 
    // xの属する集合の要素数を求める
    ll size(ll x) {
        return Siz[root(x)];
    }
};
 
int main() {
    ll n, q;
    cin >> n >> q;
 
    UnionFind Uni(n);
    rep(i, q) {
        ll t, u, v;
        cin >> t >> u >> v;
        if(t == 0) {
            Uni.unite(u, v);
        }
        else if(t == 1) {
            if(Uni.same(u, v)) {
                out(1);
            }
            else {
                out(0);
            }
        }
    }
    
    re0;
}