#include using namespace std; struct node { node *l; node *r; node *p; int val; int size; int sum; bool flip; node(){} node (int _val): l(0), r(0), p(0), val(_val), size(1), sum(_val), flip(0){} virtual void update() { size=1; sum=val; if (l) { size += l->size; sum += l->sum; } if (r) { size += r->size; sum += r->sum; } } void touch() { if (flip) { swap(l, r); if (l) l-> flip^=1; if (r) r-> flip^=1; flip=0; } } void touch_path() { if (p) p->touch_path(); touch(); } node*& get_child(bool right) { return right ? r : l; } static void add_child (node* x, node* q, bool right) { if (x) x->get_child(right) = q; if (q) q->p = x; } inline bool is_right() { return p && p->r==this; } void rotate() { if(!p) return; node *oldp = p; bool right = is_right(); add_child(p->p, this, p->is_right()); add_child(oldp, get_child(!right), right); add_child(this, oldp, !right); oldp->update(); update(); } void splay_() { while (p) { if (is_right() ^ p->is_right()) rotate(); else p->rotate(); rotate(); } } void splay() { touch_path(); splay_(); } void set_val(int nval) { val=nval; update(); } void reverse() { flip=!flip; } node* get_first() { node* res=this; while(1) { res->touch(); if (!res->l) break; res=res->l; } res->splay_(); return res; } node* remove() { if (l) l->p = nullptr; if (r) r->p = nullptr; node* root = join(l, r); l=r=nullptr; return root; } static node* join(node* a, node* b) { if (!a) return b; while(1) { a->touch(); if (!a->r) break; a=a->r; } a->splay_(); add_child(a, b, true); a->update(); return a; } node* get_kth(int k) { assert(size>k); node* res=this; while(1) { res->touch(); if (res->l){ if (res->l->size>k) { res=res->l; continue; } else k-=res->l->size; } if (k==0){ res->splay_(); return res; } k--; res=res->r; } } pair split(int k){ if(k==0)return {nullptr, this}; if(k>=size) return {this, nullptr}; node* x = get_kth(k); node* res = x->l; x->l->p = nullptr; x->l = nullptr; x->update(); return {res, x}; } virtual ~node(){delete l; delete r;} }; struct LCnode : node{ int st_size; int base_size; LCnode(){} LCnode(int val, bool ver):node(val), st_size(ver), base_size(ver){}; virtual void update() { node::update(); st_size = base_size; if(l) st_size += ((LCnode *) l)->st_size; if(r) st_size += ((LCnode *) r)->st_size; } void LCsplay() { node* ak = this; node* par = ak->p; while (par && (par->l==ak || par->r==ak)) { ak=par; par=ak->p; } ak->p=nullptr; splay(); p=par; } void access() { node* right = nullptr; LCnode* cur = this; while (cur) { cur -> LCsplay(); if (cur->r) cur ->base_size += ((LCnode*) cur->r)->st_size; if (right) cur->base_size -= ((LCnode*) right)->st_size; cur->r=right; cur->update(); right = cur; cur=(LCnode*)cur->p; } splay(); } void to_root() { access(); reverse(); touch(); } void link(LCnode* par) { to_root(); p=par; par->to_root(); par->base_size+=st_size; par->update(); } void get_path(LCnode* v){ v->to_root(); access(); } void cut(LCnode* v){ get_path(v); v->p=l=nullptr; update(); } bool connected(LCnode* v){ get_path(v); return get_first()==v; } virtual ~LCnode() { l=r=nullptr; }; }; unordered_map mapa; unordered_map kra; int32_t main() { int n, q; cin >> n >> q; for (int i=0; i> t; if (t==0) { int a, b, v; cin >> a >> b >> v; kra[1000000000ll*a+b]=v+1; for (int j=v; j<10; j++) { int na=a+j*n, nb=b+j*n; if (mapa.find(na)==mapa.end()) { mapa[na]=LCnode(na, true); } if (mapa.find(nb)==mapa.end()) { mapa[nb]=LCnode(nb, true); } mapa[na].link(&mapa[nb]); } } else if (t==1) { int a, b, v; cin >> a >> b; for (int j=0; j<10; j++) { int na=a+j*n, nb=b+j*n; if (mapa.find(na)==mapa.end()) { mapa[na]=LCnode(na, true); } if (mapa.find(nb)==mapa.end()) { mapa[nb]=LCnode(nb, true); } if (kra[1000000000ll*a+b]>j+1) { mapa[na].cut(&mapa[nb]); } } kra[1000000000ll*a+b]=0; } else { int a, b, v, czy=1; cin >> a >> b; for (int j=0; j<10; j++) { int na=a+j*n, nb=b+j*n; if (mapa.find(na)==mapa.end()) { mapa[na]=LCnode(na, 1); } if (mapa.find(nb)==mapa.end()) { mapa[nb]=LCnode(nb, 1); } if (mapa[na].connected(&mapa[nb])) { cout << j << "\n"; czy=0; break; } } if (czy==1) cout << "-1\n"; } } }