#include using namespace std; typedef long long int ll; typedef double ld; typedef vector vi; typedef vector Graph; // push_back insert lower_bound upper_bound erase #define SQRT_MULT (0.6) //unionfind struct Uf{ vector p, r; // p=element's parent, r=rank unordered_map fake_p; void clear_fake(){ fake_p.clear(); } Uf(ll n):p(n),r(n){ iota(p.begin(), p.end(), 0); } // finds representant of a's set ll find(ll a){ return p[a]==a ? a : p[a]=find(p[a]); } ll fake_find(ll a){ a = find(a); return fake_p.count(a) ? fake_find(fake_p[a]) : a; } // unifies sets of a and b void fake_uni(ll a, ll b){ a = fake_find(a); b = fake_find(b); if(a==b)return; /* if(r[a] edges[MXM]; vi v, inv; void check(ll cur_b, ll prev_b, ll bound){ ll cur_e = v[prev_b]; Uf uf(N); ll sz=0; for(ll i=cur_b; iprev_b; --j){ auto &pp=edges[j]; ll aa=pp.first; ll bb=pp.second; if(uf.same(aa,bb)){ break; } uf.fake_uni(aa,bb); v[j]=i; } uf.clear_fake(); if(uf.same(a, b)) return; uf.uni(a, b); } v[cur_b]=M; } int main(int argc, char **argv){ cin >> N >> M; g = Graph(N); for(ll i=0; i> a >> b; --a; --b; edges[i]={a,b}; g[a].push_back(b); g[b].push_back(a); } edges[M]={0,0}; ll Q; cin >> Q; vector> q(Q); for(auto &p:q) cin >> p.first >> p.second; for(auto &p:q) --p.first, --p.second; inv = v = vi(M, 0); ll bound = max(3,((int)ceil(SQRT_MULT * sqrt(M)))); ll idx=0, last=0; while(idx