#include using namespace std; struct unionfind{ vector r, p; int t; unionfind(int N): r(N * 2 - 1, -1), p(N * 2 - 1, -1), t(N){ } int root(int x){ if (r[x] == -1){ return x; } else { r[x] = root(r[x]); return r[x]; } } bool same(int x, int y){ return root(x) == root(y); } void unite(int x, int y){ x = root(x); y = root(y); if (x != y){ p[x] = t; p[y] = t; r[x] = t; r[y] = t; t++; } } }; const int LOG = 17; struct lowest_common_ancestor{ vector d; vector> pp; lowest_common_ancestor(vector &p, vector &d): d(d){ int N = p.size(); pp = vector>(LOG, vector(N, -1)); pp[0] = p; for (int i = 0; i < LOG - 1; i++){ for (int j = 0; j < N; j++){ if (pp[i][j] != -1){ pp[i + 1][j] = pp[i][pp[i][j]]; } } } } int la(int v, int k){ for (int i = 0; i < LOG; i++){ if ((k >> i & 1) == 1){ v = pp[i][v]; } } return v; } int lca(int u, int v){ if (d[u] > d[v]){ swap(u, v); } v = la(v, d[v] - d[u]); if (u == v){ return u; } for (int i = LOG - 1; i >= 0; i--){ if (pp[i][u] != pp[i][v]){ u = pp[i][u]; v = pp[i][v]; } } return pp[0][v]; } }; void dfs(vector> &c, vector &in, vector &out, int &t, int v){ in[v] = t; t++; for (int w : c[v]){ dfs(c, in, out, t, w); } out[v] = t; } #pragma once /** * @brief 双対可逆 Binary Indexed Tree */ template struct dual_invertible_binary_indexed_tree{ int N; vector BIT; function f; function inv; T E; dual_invertible_binary_indexed_tree(int N, function f, function inv, T E): N(N), BIT(N + 1, E), f(f), inv(inv), E(E){ } void add(int i, T x){ while (i > 0){ BIT[i] = f(BIT[i], x); i -= i & -i; } } void add(int l, int r, T x){ add(l, inv(x)); add(r, x); } T operator [](int i){ i++; T ans = E; while (i <= N){ ans = f(ans, BIT[i]); i += i & -i; } return ans; } }; int main(){ int N, Q; cin >> N >> Q; unionfind UF(N); vector> query; for (int i = 0; i < Q; i++){ int T, A, B; cin >> T >> A >> B; if (T == 1){ A--; B--; UF.unite(A, B); } if (T == 2){ A--; query.push_back(make_tuple(0, UF.root(A), B)); } if (T == 3){ A--; query.push_back(make_tuple(1, A, 0)); } } vector p = UF.p; p.push_back(-1); for (int i = 0; i < N * 2 - 1; i++){ if (p[i] == -1){ p[i] = N * 2 - 1; } } vector> c(N * 2); for (int i = 0; i < N * 2 - 1; i++){ c[p[i]].push_back(i); } vector in(N * 2), out(N * 2); int t = 0; dfs(c, in, out, t, N * 2 - 1); dual_invertible_binary_indexed_tree BIT(N * 2, plus(), negate(), 0); int M = query.size(); for (int i = 0; i < M; i++){ if (get<0>(query[i]) == 0){ int v = get<1>(query[i]); int x = get<2>(query[i]); BIT.add(in[v], out[v], x); } if (get<0>(query[i]) == 1){ int v = get<1>(query[i]); cout << BIT[in[v]] << endl; } } }