#include #define rep(i,n) for(int i=0;i<(int)(n);i++) using namespace std; using ll = long long ; using P = pair ; using pll = pair; constexpr int INF = 1e9; constexpr long long LINF = 1e17; constexpr int MOD = 1000000007; struct potential_Unionfind{ vector parents; vector weights; int m; potential_Unionfind(int n):parents(n,-1){ m = n; weights.resize(n); } int find(int x){ if(parents[x] < 0) return x; else{ int p = find(parents[x]); weights[x] += weights[parents[x]]; return parents[x] = p; } } //weight[y] - weights[x] = wとなるようにuniteする。 bool unite(int x,int y,int w){ w += weight(x); w -= weight(y); x = find(x); y = find(y); if(x == y) return false;//もうすでに繋がれている頂点ならfalseを返す if(parents[x] > parents[y]) {swap(x,y); w = -w;} parents[x] += parents[y]; parents[y] = x; weights[y] = w; return true; } bool same(int x,int y){ return find(x) == find(y); } //weightsは各頂点から根までの距離 int weight(int x){ find(x); return weights[x]; } //まずsame(x,y)で繋がっているかわからないと正しい答えは出てこない int diff(int x,int y){ return weight(y) - weight(x); } }; int main(){ int n,q; scanf("%d %d",&n,&q); //cin >> n >> q; potential_Unionfind uf(n); vector sum(n,0); rep(i,q){ int t,a,b; scanf("%d %d %d",&t,&a,&b); //cin >> t >> a >> b; if(t==1){ --a;--b; int k = uf.find(a); int ka = sum[k] + uf.diff(k,a); int l = uf.find(b); int lb = sum[l] + uf.diff(l,b); uf.unite(a,b,lb-ka); }else if(t==2){ --a; sum[uf.find(a)] += b; }else if(t==3){ --a; int p = uf.find(a); printf("%d \n",sum[p] + uf.diff(p,a)); //cout << sum[p] + uf.diff(p,a)<< endl ; //cout << uf.diff(p,a) << endl; } } return 0; }