#include #include #include #include using namespace __gnu_pbds; using namespace std; #define endl "\n" #define mp make_pair #define st first #define nd second #define pii pair #define pb push_back #define _upgrade ios_base::sync_with_stdio(0), cout.setf(ios::fixed), cout.precision(10), cin.tie(0), cout.tie(0); #define rep(i, n) for (int i = 0; i < (n); ++i) #define fwd(i, a, b) for (int i = (a); i < (b); ++i) #define trav(a, x) for (auto &a : x) #define all(c) (c).begin(), (c).end() #define sz(X) (int)((X).size()) typedef long double ld; typedef unsigned long long ull; typedef long long ll; typedef tree, rb_tree_tag, tree_order_statistics_node_update> indexed_set; // find_by_order(x) <-returns x-th element order_of_key(x) <- returns order of element x // mt19937_64 gen(chrono::steady_clock::now().time_since_epoch().count());uniform_int_distribution distr(0, 1e9);auto my_rand = bind(distr, gen); // my_rand() zwraca teraz liczbe z przedzialu [a, b] #ifdef LOCAL ostream &operator<<(ostream &out, string str) { for (char c : str) out << c; return out; } template ostream &operator<<(ostream &out, pair p) { return out << "(" << p.st << ", " << p.nd << ")"; } template ostream &operator<<(ostream &out, tuple p) { auto &[a, b, c] = p; return out << "(" << a << ", " << b << ", " << c << ")"; } template auto operator<<(ostream &out, T a) -> decltype(a.begin(), out) { out << '{'; for (auto it = a.begin(); it != a.end(); it = next(it)) out << (it != a.begin() ? ", " : "") << *it; return out << '}'; } void dump() { cerr << "\n"; } template void dump(T a, Ts... x) { cerr << a << ", "; dump(x...); } #define debug(...) cerr << "[" #__VA_ARGS__ "]: ", dump(__VA_ARGS__) #else #define debug(...) 42 #endif // Source : https : // github.com/ngthanhtrung23/ACM_Notebook_new/blob/master/DataStructure/LinkCut.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 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; } 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 (push_flip(); p;) { if (p->p) p->p->push_flip(); p->push_flip(); push_flip(); 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. push_flip(); 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)); make_root(&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]; make_root(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 make_root(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; } }; #define int long long #define r1 ((l + r) / 2) // ulatwia branie srodka przedzialu #define l2 (r1 + 1) struct SegmentTree { // drzewo przedział-przedział (add,sum) struct content { int mod; int sum; }; vector C; int size; SegmentTree(int x) { size = (1 << (32 - __builtin_clz(x))), C.resize(size * 2); } // drzewo przedzialowe dla zakresu [0,x), void add(int p, int q, int val, int l, int r, int wezel = 1) { // dodaje val do przedzialu [p,q] if (p > q) return; if (p == l && q == r) { C[wezel].mod += val; C[wezel].sum += (q - p + 1) * val; return; } add(p, min(r1, q), val, l, r1, 2 * wezel); add(max(l2, p), q, val, l2, r, 2 * wezel + 1); C[wezel].sum = C[2 * wezel].sum + C[2 * wezel + 1].sum + C[wezel].mod * (r - l + 1); } int query(int p, int q, int l, int r, int wezel = 1) { // suma na przedzial [p,q] if (p > q) return 0; if (p == l && q == r) return C[wezel].sum; return query(p, min(r1, q), l, r1, 2 * wezel) + query(max(l2, p), q, l2, r, 2 * wezel + 1) + C[wezel].mod * (q - p + 1); } void add(int p, int q, int val) { add(p, q, val, 0, size - 1); } int query(int p, int q) { return query(p, q, 0, size - 1); } }; #define tpl tuple int32_t main() { _upgrade; int n, m; cin >> n >> m; LinkCut L(n); vector P(m); rep(i, m) cin >> P[i].st >> P[i].nd; int j = 0; vector V(m); rep(i, m) { while (j < m) { auto [u, v] = P[j]; --u, --v; if (L.connected(u, v)) break; L.link(u, v); j++; } L.cut(P[i].st - 1, P[i].nd - 1); V[i] = j - 1; } debug(V); int q; cin >> q; vector Q; rep(i, q) { int a, b; cin >> a >> b; Q.emplace_back(--a, --b, i); } vector res(q); sort(all(Q)); reverse(all(Q)); j = m - 1; SegmentTree S(m); for (auto [a, b, i] : Q) { debug(a, b, i); while (j >= a) { int q = V[j]; int p = j; S.add(p, q, 1); j--; } res[i] = S.query(a, b); } for (auto r : res) cout << r << endl; }