#include #include #include #include using namespace std; int N,Q; struct str{ int ix; int type; int x,y; int end; int lvl; }; const int MAXN = 1e6; int tab[MAXN]; int k; vector queries; vector queries_cleared; int result[MAXN]; map, int > M; vector type2 [MAXN]; void clear_queries() { for(auto const& x : queries) if(x.type == 0) queries_cleared.push_back(x); } int find(int k) { while(tab[k] != k) k = tab[k]; return k; } void unio(int a, int b, vector > & v) { //cerr << a << " "<< b << endl; a = find(a); b = find(b); if(rand() % 2) swap(a, b); v.push_back({ a, tab[a]}); tab[a] = b; } void g(int l, int r, vector const& v) { //cerr << l<< " " << r << " " << v.size() << endl; vector > to_rev; vector vl, vr; for(auto const& x : v) { if(x.ix >= r || x.end <= l) continue; if(x.ix <= l && x.end >= r) { unio(x.x, x.y, to_rev); continue; } vl.push_back(x); vr.push_back(x); } if(l+1 != r) { int m = (l+r)/2; g(l, m, vl); g(m, r, vr); } if(l+1 == r) { for(auto const& x : type2[l]) { if(find(x.x) == find(x.y)) result[x.ix] = k; } } for(int i=to_rev.size()-1; i>=0; i--) { auto const& x = to_rev[i]; tab[x.first] = x.second; } } void f() { for(int i=0; i<=N; i++) tab[i] = i; vector v; for(auto const& x : queries_cleared) if(x.type == 0 && x.lvl <= k) v.push_back(x); g(0, Q, v); } int32_t main(){ ios_base::sync_with_stdio(0); cin.tie(0); cin >> N >> Q; for(int i=0; i> s.type; s.ix = i; if(s.type == 2) { cin >> s.x >> s.y; queries.push_back(s); type2[i].push_back(s); continue; } if(s.type == 0) { cin >> s.x >> s.y >> s.lvl; M[{s.x,s.y}] = i; queries.push_back(s); continue; } if(s.type == 1) { cin >> s.x >> s.y; queries[M[{s.x,s.y}]].end = i + 1; queries.push_back(s); } } assert(queries.size() == Q); k = 9; clear_queries(); while(k >= 0) { f(); k--; } for(int i=0; i