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)

#define _USE_MATH_DEFIMES
#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <climits>
#include <clocale>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <regex>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

const int MOD = 1'000'000'007;
const int INF = 1'000'000'000; //1e9
const int NIL = -1;
const long long LINF = 1'000'000'000'000'000'000; // 1e18
const long double EPS = 1E-10;

template<class T, class S> inline bool chmax(T &a, const S &b){
    if(a < b){
        a = b; return true;
    }
    return false;
}
template<class T, class S> inline bool chmin(T &a, const S &b){
    if(b < a){
        a = b; return true;
    }
    return false;
}







#include <algorithm>
#include <vector>


class UnionFind{
    int n;
    std::vector<int> par;//根ならマイナス*要素数

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

    void resize(int N){
        n = N;
        par.resize(n, -1);
    }

    int find(int x){
        if(par[x] < 0) return x;
        else return par[x] = find(par[x]);
    }

    bool unit(int x, int y){
        x = find(x);
        y = find(y);
        if(x == y) return false;

        if(-par[x] < -par[y]) std::swap(x, y); 
        par[x] += par[y];
        par[y] = x;
        return true;
    }

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

    int howmany(int x){ //同じグループに属すものの個数(自分を含む)
        return -par[find(x)];
    }

    std::vector<std::vector<int>> groups(){
        std::vector<int> rtbuf(n), gsz(n);
        for(int i(0); i < n; ++i){
            rtbuf[i] = find(i);
            ++gsz[rtbuf[i]];
        }
        std::vector<std::vector<int>> ret(n);
        for(int i(0); i < n; ++i){
            ret[i].reserve(gsz[i]);
        }
        for(int i(0); i < n; ++i){
            ret[rtbuf[i]].push_back(i);
        }
        ret.erase(
            std::remove_if(std::begin(ret), std::end(ret),
                [&](const std::vector<int>& v) { return v.empty(); }),
            std::end(ret));
        return ret;
    }
};


int main(){
    int N, Q; std::cin >> N >> Q;
    UnionFind d(N);
    std::vector<std::vector<int>> ls;
    {
        int t, u, v;
        for(int i(0); i < Q; ++i){
            std::cin >> t >> u >> v;
            if(t){
                std::cout << d.same(u, v) << "\n";
            }else d.unit(u, v);
        }
    }
    return 0;
}