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 Rust (1.42.0) (judge verdict: Accepted)

#![allow(unused_imports)]
#![allow(non_snake_case)]
use std::cmp::*;
use std::collections::*;
use std::ops::Bound::*;
use itertools::Itertools;
use num_traits::clamp;
use ordered_float::OrderedFloat;
use proconio::{input, marker::*, fastout};
use superslice::*;

#[fastout]
fn main() {
    input! {
        n: usize, q: usize,
        tuv: [(usize, usize, usize); q]
    }

    let mut dsu = DSU::new(n);
    
    for (t, u, v) in tuv {
        match t {
            0 => {
                dsu.merge(u, v);
            }
            1 => {
                let res = (dsu.leader(u) == dsu.leader(v)) as u32;
                println!("{}", res);
            }
            _ => unreachable!()
        }
    }
}
#[allow(dead_code)]
pub struct DSU {
    parent_or_size: Vec<isize>,
}

#[allow(dead_code)]
impl DSU {
    pub fn new(n: usize) -> Self {
        assert!(n <= std::isize::MAX as usize);
        Self {
            parent_or_size: vec![-1; n],
        }
    }

    pub fn merge(&mut self, a: usize, b: usize) -> usize {
        let mut x = self.leader(a);
        let mut y = self.leader(b);
        if x == y {
            return x;
        }
        if -self.parent_or_size[x] < -self.parent_or_size[y] {
            std::mem::swap(&mut x, &mut y);
        }
        self.parent_or_size[x] += self.parent_or_size[y];
        self.parent_or_size[y] = x as isize;
        x
    }

    pub fn same(&mut self, a: usize, b: usize) -> bool {
        self.leader(a) == self.leader(b)
    }

    pub fn leader(&mut self, a: usize) -> usize {
        if self.parent_or_size[a] < 0 {
            a
        } else {
            self.parent_or_size[a] = self.leader(self.parent_or_size[a] as usize) as isize;
            self.parent_or_size[a] as usize
        }
    }

    pub fn size(&mut self, a: usize) -> usize {
        let leader = self.leader(a);
        -self.parent_or_size[leader] as usize
    }

    pub fn groups(&mut self) -> Vec<Vec<usize>> {
        let mut leader_buf = vec![0usize; self.parent_or_size.len()];
        let mut group_size = vec![0usize; self.parent_or_size.len()];
        for i in 0..self.parent_or_size.len() {
            leader_buf[i] = self.leader(i);
            group_size[leader_buf[i]] += 1;
        }
        let mut result = vec![Vec::new(); self.parent_or_size.len()];
        for i in 0..self.parent_or_size.len() {
            result[i].reserve(group_size[i]);
        }
        for i in 0..self.parent_or_size.len() {
            result[leader_buf[i]].push(i);
        }
        result.retain(|v| !v.is_empty());
        result
    }
}