//source https://github.com/kth-competitive-programming/kactl/blob/main/content/contest/template.cpp #include using namespace std; #define rep(i, a, b) for(int i = a; i < (b); ++i) #define all(x) begin(x), end(x) #define sz(x) (int)(x).size() typedef long long ll; typedef pair pii; typedef vector vi; //source https://github.com/kth-competitive-programming/kactl/blob/main/content/graph/LinkCutTree.h struct Node { // Splay tree. Root's pp contains tree's parent. Node *p = 0, *pp = 0, *c[2]; bool flip = 0; Node() { c[0] = c[1] = 0; fix(); } void fix() { if (c[0]) c[0]->p = this; if (c[1]) c[1]->p = this; // (+ update sum of subtree elements etc. if wanted) } void pushFlip() { if (!flip) return; flip = 0; swap(c[0], c[1]); if (c[0]) c[0]->flip ^= 1; if (c[1]) c[1]->flip ^= 1; } int up() { return p ? p->c[1] == this : -1; } void rot(int i, int b) { int h = i ^ b; Node *x = c[i], *y = b == 2 ? x : x->c[h], *z = b ? y : x; if ((y->p = p)) p->c[up()] = y; c[i] = z->c[i ^ 1]; if (b < 2) { x->c[h] = y->c[h ^ 1]; z->c[h ^ 1] = b ? x : this; } y->c[i ^ 1] = b ? this : x; fix(); x->fix(); y->fix(); if (p) p->fix(); swap(pp, y->pp); } void splay() { /// Splay this up to the root. Always finishes without flip set. for (pushFlip(); p; ) { if (p->p) p->p->pushFlip(); p->pushFlip(); pushFlip(); int c1 = up(), c2 = p->up(); if (c2 == -1) p->rot(c1, 2); else p->p->rot(c2, c1 != c2); } } Node* first() { /// Return the min element of the subtree rooted at this, splayed to the top. pushFlip(); return c[0] ? c[0]->first() : (splay(), this); } }; struct LinkCut { vector node; LinkCut(int N) : node(N) {} void link(int u, int v) { // add an edge (u, v) assert(!connected(u, v)); makeRoot(&node[u]); node[u].pp = &node[v]; } void cut(int u, int v) { // remove an edge (u, v) Node *x = &node[u], *top = &node[v]; makeRoot(top); x->splay(); assert(top == (x->pp ?: x->c[0])); if (x->pp) x->pp = 0; else { x->c[0] = top->p = 0; x->fix(); } } bool connected(int u, int v) { // are u, v in the same tree? Node* nu = access(&node[u])->first(); return nu == access(&node[v])->first(); } void makeRoot(Node* u) { /// Move u to root of represented tree. access(u); u->splay(); if(u->c[0]) { u->c[0]->p = 0; u->c[0]->flip ^= 1; u->c[0]->pp = u; u->c[0] = 0; u->fix(); } } Node* access(Node* u) { /// Move u to root aux tree. Return the root of the root aux tree. u->splay(); while (Node* pp = u->pp) { pp->splay(); u->pp = 0; if (pp->c[1]) { pp->c[1]->p = 0; pp->c[1]->pp = pp; } pp->c[1] = u; pp->fix(); u = pp; } return u; } }; int main() { #define int long long cin.tie(0)->sync_with_stdio(0); cin.exceptions(cin.failbit); int n, m; cin >> n >> m; vector a(m), b(m), S(m); for(int i = 0; i < m; ++i){ S[i] = i; cin >> a[i] >> b[i]; } int en = 0; LinkCut A(n+1); for(int i = 0; i < m; ++i){ if(en == i){ A.link(a[en], b[en]); en++; } while(en != m && !A.connected(a[en], b[en])) { A.link(a[en], b[en]); en++; } S[i] = en-1; A.cut(a[i],b[i]); } vector sp(m+1); sp[0] = 0; for(int i = 0; i < m; ++i){ sp[i+1] = sp[i] + S[i]; } vector sp2(m+1); sp2[0] = 0; for(int i = 0; i < m; ++i){ sp2[i+1] = sp2[i] + i; } S.push_back(1e9); int q; cin >> q; int it = 0; while(q--){ ++it; int c,d; cin >> c >> d; --c; --d; int x = 0; int w = lower_bound(S.begin()+c, S.end(), d) - S.begin(); if(c == d){ x = 1; } else if(w > d){ x = sp[d+1] - sp[c]; x -= (sp2[d+1] - sp2[c]); x += d-c+1; } else if(w <= c){ x = (d*(d-c+1)); x -= (sp2[d+1] - sp2[c]); x += d-c+1; } else { { x = sp[w-1+1] - sp[c]; x -= (sp2[w-1+1] - sp2[c]); x += w-1-c+1; } { x += (d*(d-w+1)); x -= (sp2[d+1] - sp2[w]); x += d-w+1; } } cout << x << '\n'; } }