//vsp #include #define cat(x) cerr << #x << " = " << x << "\n"; #define rep(i, a, b) for (int i = (a); i < (b); i++) #define per(i, a, b) for (int i = (b) - 1; (a) <= i; i--) #define FOR(i, n) for (int i = 0; i < (n); i++) #define sz(x) int(x.size()) #define pb push_back using ll = long long; using namespace std; //https://codeforces.com/blog/entry/75885 struct SplayTree { struct Node { int ch[2] = {0, 0}, p = 0; long long self = 0, path = 0; // Path aggregates long long sub = 0, vir = 0; // Subtree aggregates bool flip = 0; // Lazy tags }; vector T; SplayTree(int n) : T(n + 1) {} void push(int x) { if (!x || !T[x].flip) return; int l = T[x].ch[0], r = T[x].ch[1]; T[l].flip ^= 1, T[r].flip ^= 1; swap(T[x].ch[0], T[x].ch[1]); T[x].flip = 0; } void pull(int x) { int l = T[x].ch[0], r = T[x].ch[1]; push(l); push(r); T[x].path = T[l].path + T[x].self + T[r].path; T[x].sub = T[x].vir + T[l].sub + T[r].sub + T[x].self; } void set(int x, int d, int y) { T[x].ch[d] = y; T[y].p = x; pull(x); } void splay(int x) { auto dir = [&](int x) { int p = T[x].p; if (!p) return -1; return T[p].ch[0] == x ? 0 : T[p].ch[1] == x ? 1 : -1; }; auto rotate = [&](int x) { int y = T[x].p, z = T[y].p, dx = dir(x), dy = dir(y); set(y, dx, T[x].ch[!dx]); set(x, !dx, y); if (~dy) set(z, dy, x); T[x].p = z; }; for (push(x); ~dir(x); ) { int y = T[x].p, z = T[y].p; push(z); push(y); push(x); int dx = dir(x), dy = dir(y); if (~dy) rotate(dx != dy ? x : y); rotate(x); } } }; struct LinkCut : SplayTree { LinkCut(int n) : SplayTree(n) {} int access(int x) { int u = x, v = 0; for (; u; v = u, u = T[u].p) { splay(u); int& ov = T[u].ch[1]; T[u].vir += T[ov].sub; T[u].vir -= T[v].sub; ov = v; pull(u); } return splay(x), v; } void reroot(int x) { access(x); T[x].flip ^= 1; push(x); } void Link(int u, int v) { reroot(u); access(v); T[v].vir += T[u].sub; T[u].p = v; pull(v); } void Cut(int u, int v) { reroot(u); access(v); T[v].ch[0] = T[u].p = 0; pull(v); } // Rooted tree LCA. Returns 0 if u and v arent connected. int LCA(int u, int v) { if (u == v) return u; access(u); int ret = access(v); return T[u].p ? ret : 0; } // Query subtree of u where v is outside the subtree. long long Subtree(int u, int v) { reroot(v); access(u); return T[u].vir + T[u].self; } // Query path [u..v] long long Path(int u, int v) { reroot(u); access(v); return T[v].path; } // Update vertex u with value v void Update(int u, long long v) { access(u); T[u].self = v; pull(u); } }; const int N = 2e5; int n, m, go[N]; int x[N], y[N]; vector> res[N]; template struct sum_tree { T s[2 * N]; T query(int l, int r) { T res = 0; for (l += N, r += N + 1; l < r; l /= 2, r /= 2) { if (l & 1) res += s[l++]; if (r & 1) res += s[--r]; } return res; } void update(int u, T x) { u += N; s[u] = x; for (u /= 2; u; u /= 2) s[u] = s[2 * u] + s[2 * u + 1]; } void add(int u, T x) { update(u, x + query(u, u)); } void init(vector a) { int n = sz(a); FOR(i, n) update(i, a[i]); } }; sum_tree cnt, A, B; vector ogar[N]; ll ans[N]; int main() { cin.tie(0)->sync_with_stdio(0); cin >> n >> m; rep(i, 1, m + 1) { cin >> x[i] >> y[i]; } LinkCut T(n); int j = 0; rep(i, 1, m + 1) { if (i > 1) T.Cut(x[i - 1], y[i - 1]); while (j + 1 <= m && T.LCA(x[j + 1], y[j + 1]) == 0) { T.Link(x[j + 1], y[j + 1]); j++; } go[i] = j; ogar[go[i]].push_back(i); } int q; cin >> q; FOR(i, q) { int a, b; cin >> a >> b; res[b].emplace_back(a, i); } rep(i, 1, m + 1) { cnt.update(i, 1); A.update(i, -i); } rep(i, 1, m + 1) { for (auto x : ogar[i]) { cnt.update(x, 0); A.update(x, 0); B.update(x, go[x] - x + 1); } for (auto [l, id] : res[i]) { ans[id] = B.query(l, i) + 1ll * (i + 1) * cnt.query(l, i) + A.query(l, i); } } FOR(i, q) cout << ans[i] << '\n'; return 0; }