#include #define mp make_pair #define fi first #define se second #define pb push_back #define all(x) (x).begin(),(x).end() using namespace std; typedef long long LL; typedef unsigned long long uLL; typedef pair PII; typedef vector < int > VI; typedef double D; const int MN = 100005, inf = 1000000005, mod = 1000000007; const LL INF = 1000000000000000005LL; // Code of link-cut tree from // https://github.com/Skedar1994/Kody/blob/master/kody/link-cut-tree.cpp template struct splnode { typedef splnode node_t; splnode() : P(NULL), flip(0), pp(NULL) { C[0] = C[1] = NULL; fix(); } node_t* P; node_t* C[2]; int flip; node_t* pp; /* Fix the parent pointers of our children. Additionally if we have any * extra data we're tracking (e.g. sum of subtree elements) now is the time to * update them (all of the children will already be up to date). */ void fix() { if(C[0]) C[0]->P = this; if(C[1]) C[1]->P = this; } /* Push the flip bit down the tree. */ void push_flip() { if(!flip) return; flip = 0; swap(C[0], C[1]); if(C[0]) C[0]->flip ^= 1; if(C[1]) C[1]->flip ^= 1; } /* Return the direction of this relative its parent. */ int up() { return !P ? -1 : (P->C[0] == this ? 0 : 1); } /* Simple zig step in the 'c' direction when we've reached the root. */ void zig(int c) { node_t* X = C[c]; if(X->P = P) P->C[up()] = X; C[c] = X->C[1 - c]; X->C[1 - c] = this; fix(); X->fix(); if(P) P->fix(); swap(pp, X->pp); } /* Zig zig in the 'c' direction both times. */ void zigzig(int c) { node_t* X = C[c]; node_t* Y = X->C[c]; if(Y->P = P) P->C[up()] = Y; C[c] = X->C[1 - c]; X->C[c] = Y->C[1 - c]; Y->C[1 - c] = X; X->C[1 - c] = this; fix(); X->fix(); Y->fix(); if(P) P->fix(); swap(pp, Y->pp); } /* Zig zag first in the 'c' direction then in the '1-c' direciton. */ void zigzag(int c) { node_t* X = C[c]; node_t* Y = X->C[1 - c]; if(Y->P = P) P->C[up()] = Y; C[c] = Y->C[1 - c]; X->C[1 - c] = Y->C[c]; Y->C[1 - c] = this; Y->C[c] = X; fix(); X->fix(); Y->fix(); if(P) P->fix(); swap(pp, Y->pp); } /* Splay this up to the root. Always finishes without flip set. */ node_t* splay() { for(push_flip(); P; ) { /* Reorganize flip bits so we can rotate as normal. */ if(P->P) P->P->push_flip(); P->push_flip(); push_flip(); int c1 = up(); int c2 = P->up(); if(c2 == -1) { P->zig(c1); } else if(c1 == c2) { P->P->zigzig(c1); } else { P->P->zigzag(c2); } } return this; } /* Return the max element of the subtree rooted at this. */ node_t* last() { push_flip(); return C[1] ? C[1]->last() : splay(); } /* Return the min element of the subtree rooted at this. */ node_t* first() { push_flip(); return C[0] ? C[0]->first() : splay(); } }; template struct linkcut { typedef splnode node_t; linkcut(int N) : node(N) { } void link(int u, int v) { make_root(v); node[v].pp = &node[u]; } void cut(int u, int v) { make_root(u); node[v].splay(); if(node[v].pp) { node[v].pp = NULL; } else { node[v].C[0]->P = NULL; node[v].C[0] = NULL; node[v].fix(); } } bool connected(int u, int v) { node_t* nu = access(u)->first(); node_t* nv = access(v)->first(); return nu == nv; } /* Move u to root of represented tree. */ void make_root(int u) { access(u); node[u].splay(); if(node[u].C[0]) { node[u].C[0]->P = NULL; node[u].C[0]->flip ^= 1; node[u].C[0]->pp = &node[u]; node[u].C[0] = NULL; node[u].fix(); } } /* Move u to root aux tree. Return the root of the root aux tree. */ splnode* access(int u) { node_t* x,* pp; for(x = node[u].splay(); x->pp; x = pp) { pp = x->pp->splay(); x->pp = NULL; if(pp->C[1]) { pp->C[1]->P = NULL; pp->C[1]->pp = pp; } pp->C[1] = x; pp->fix(); } return x; } vector node; }; // end of link-cut tree const int P2 = (1 << 17), MTS = 2 * P2 + 5; LL lazy[MTS]; LL suma[MTS]; LL ans[MN]; PII E[MN]; int lewy[MN]; vector < PII > Q[MN]; void propagate(int x, int len) { int le = (x << 1), pr = le + 1, hf = (len >> 1); lazy[le] += lazy[x]; lazy[pr] += lazy[x]; suma[le] += lazy[x] * hf; suma[pr] += lazy[x] * hf; lazy[x] = 0; } void add(int a, int b, int cur = 1, int l = 0, int r = P2 - 1) { if(a == l && b == r) { suma[cur] += 1LL * (r - l + 1); lazy[cur]++; return; } propagate(cur, r - l + 1); int le = (cur << 1), pr = le + 1, mid = (l + r) >> 1; if(a <= mid) add(a, min(b, mid), le, l, mid); if(b > mid) add(max(a, mid + 1), b, pr, mid + 1, r); suma[cur] = suma[le] + suma[pr]; } LL ask(int a, int b, int cur = 1, int l = 0, int r = P2 - 1) { if(a == l && b == r) return suma[cur]; LL ret = 0LL; propagate(cur, r - l + 1); int le = (cur << 1), pr = le + 1, mid = (l + r) >> 1; if(a <= mid) ret += ask(a, min(b, mid), le, l, mid); if(b > mid) ret += ask(max(a, mid + 1), b, pr, mid + 1, r); //suma[cur] = suma[le] + suma[pr]; return ret; } int main() { int n, m; scanf("%d%d", &n, &m); for(int i = 1; i <= m; ++i) scanf("%d%d", &E[i].fi, &E[i].se); int q; scanf("%d", &q); for(int i = 1; i <= q; ++i) { int l, r; scanf("%d%d", &l, &r); Q[l].pb({r, i}); } linkcut tr(n + 1); int kon = 1; for(int i = 1; i <= m; ++i) { while(kon <= m) { if(tr.connected(E[kon].fi, E[kon].se)) break; tr.link(E[kon].fi, E[kon].se); ++kon; } lewy[i] = kon - 1; tr.cut(E[i].fi, E[i].se); } for(int i = m; i > 0; --i) { add(i, lewy[i]); for(auto zap : Q[i]) ans[zap.se] = ask(i, zap.fi); } for(int i = 1; i <= q; ++i) printf("%lld\n", ans[i]); }