#include using namespace std; #include //using namespace atcoder; using ll = long long; using ull = unsigned long long; using i128 = __int128_t; using u128 = unsigned __int128_t; using mint = atcoder::static_modint<998244353>; const int mod = 998244353; #include mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count()); int dx[8] = {-1, 1, 0, 0, -1, -1, 1, 1}; int dy[8] = {0, 0, -1, 1, -1, 1, -1, 1}; template bool chmin(T& a, const T& b){ if (b < a){ a = b; return true; } else { return false; } } template bool chmax(T& a, const T& b){ if (a < b){ a = b; return true; } else { return false; } } struct Unionfind{ vector par, sz; vector w; Unionfind(int n) : par(n), sz(n, 1), w(n, 0){ iota(par.begin(), par.end(), 0); } int leader(int a){ while(a != par[a]){ a = par[a]; } return a; } bool same(int a, int b){ return leader(a) == leader(b); } //w[b] - w[a] == cを満たさなかったら-1, 満たすならleaderを返す。 int merge(int b, int a){ a = leader(a); b = leader(b); if (sz[a] < sz[b]){ swap(a, b); } sz[a] += sz[b]; par[b] = a; w[b] -= w[a]; return a; } int size(int a){ return sz[leader(a)]; } vector> groups(){ int n = par.size(); vector> result(n), filtered; for (int i = 0; i < n; i++){ int r = leader(i); result[r].push_back(i); } for (int i = 0; i < n; i++){ if (!result[i].empty()){ filtered.push_back(result[i]); } } return filtered; } ll weight(int a){ ll now = w[a]; while(a != par[a]){ a = par[a]; now += w[a]; } return now; } ll diff(int a, int b){ return weight(b) - weight(a); } void add(int a, int wd){ w[leader(a)] += wd; return; } }; void solve(){ int n, q; cin >> n >> q; Unionfind uf(n); while(q--){ int a, b, c; cin >> a >> b >> c; if (a == 1){ if (!uf.same(b - 1, c - 1)){ uf.merge(b - 1, c - 1); } } else if (a == 2){ uf.add(b - 1, c); } else { cout << uf.weight(b - 1) << '\n'; } } }; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int t = 1; while(t--){ cout << fixed << setprecision(15); solve(); } }