#include using namespace std; #define PII pair #define VI vector #define VPII vector #define LL long long #define LD long double #define f first #define s second #define MP make_pair #define PB push_back #define endl '\n' #define ALL(c) (c).begin(), (c).end() #define SIZ(c) (int)(c).size() #define REP(i, n) for(int i = 0; i < (int)(n); ++i) #define FOR(i, b, e) for(int i = (b); i <= (int)(e); ++i) #define FORD(i, b, e) for(int i = (b); i >= (int)(e); --i) #define ll LL #define st f #define nd s #define pb PB #define mp MP #define eb emplace_back #define siz(c) SIZ(c) const int inf = 1e9+7; const ll INF = 1e18L+7; #define sim template ostream & operator << (ostream &p, pair x) {return p << "<" << x.f << ", " << x.s << ">";} sim> auto operator << (ostream &p, n y) -> typename enable_if::value, decltype(y.begin(), p)>::type {int o = 0; p << "{"; for(auto c: y) {if(o++) p << ", "; p << c;} return p << "}";} void dor() {cerr << endl;} sim, class...s> void dor(n p, s...y) {cerr << p << " "; dor(y...);} sim, class s> void mini(n &p, s y) {if(p>y) p = y;} sim, class s> void maxi(n &p, s y) {if(p #include using namespace __gnu_pbds; template using ordered_set = tree, rb_tree_tag, tree_order_statistics_node_update>; #else #include #endif struct Splay { Splay *l = 0, *r = 0, *p = 0; bool flip = false; // Wywal jak nie używasz make_root. int roz = 1; // SUBTREE Rozmiar poddrzewa. Wszystko z SUBTREE opcjonalne. int axroz = 1; // SUBTREE Pomocniczny rozmiar poddrzewa. void update() { assert(!flip and (!l or !l->flip) and (!r or !r->flip)); axroz = roz; // SUBTREE if (l) axroz += l->axroz; // SUBTREE if (r) axroz += r->axroz; // SUBTREE } void touch() { if (flip) { swap(l, r); if (l) l->flip = !l->flip; if (r) r->flip = !r->flip; flip = false; } } bool sroot() { return !p or (p->l != this and p->r != this); } void connect(Splay* c, bool left) { (left ? l : r) = c; if (c) c->p = this; } void rotate() { Splay* f = p; Splay* t = f->p; const bool isr = f->sroot(); const bool left = (this == f->l); f->connect(left ? r : l, left); connect(f, !left); if (isr) p = t; else t->connect(this, f == t->l); f->update(); } void push() { sroot() ? touch() : p->push(); if (l) l->touch(); if (r) r->touch(); } void splay() { push(); while (!sroot()) { Splay* x = p->p; if (!p->sroot()) (((p->l == this) == (x->l == p)) ? p : this)->rotate(); rotate(); } update(); } Splay* expose() { // v będzie korzeniem splaya zawierającego ścieżkę do korzenia. Prawe dziecko Splay *q = this, *x = 0; // będzie nullem. Jak zejdziemy w dół, to potem trzeba zrobić splay(). while (q) { // LCA(u, v): u->expose(); ret v->expose(); q->splay(); if (q->r) q->roz += q->r->axroz; // SUBTREE if (x) q->roz -= x->axroz; // SUBTREE q->r = x; q->update(); x = q; q = q->p; } splay(); return x; } Splay* root() { // Zwraca roota drzewowego (nie splejowego!). expose(); Splay* s = this; while (s->touch(), s->l) s = s->l; s->splay(); return s; } void cut() { // Usuwa krawędź znajdującą się nad danym wierzchołkiem. expose(); assert(l /* Nie jest rootem. */); Splay* s = l; while (s->touch(), s->r) s = s->r; s->splay(); s->r->p = 0; s->r = 0; } void link(Splay* to) { expose(); assert(!l /* Jest rootem. */); p = to; p->expose(); p->roz += axroz; p->axroz += axroz; // SUBTREE } // Sprawia, że wierzchołek jest rootem w logicznym i w splayowym drzewie. void make_root() { expose(); flip = !flip; touch(); } }; /////////////////////////////////////////////// struct node { node *L, *R; int prior, sub, lazy; // sub opcjonalne PII ind; ll sum; node(PII ind) : L(0), R(0), ind(ind), prior(rand()), sub(1), lazy(0), sum(ind.st) {} }; void rev(node* v) { // example update function for subtree, reverses nodes v->lazy ^= 1; swap(v->L, v->R); } void push(node* v) { // opcjonalne if (v->lazy) { if (v->L) rev(v->L); if (v->R) rev(v->R); v->lazy = 0; } } node* attach(node* v, node* l, node* r) { v->L = l; // jesli chcemy trzymac ojca to update w tej funkcji v->R = r; v->sub = 1 + (l ? l->sub : 0) + (r ? r->sub : 0); //sub opcjonalne v->sum = v->ind.st + (l ? l->sum : 0) + (r ? r->sum : 0); return v; } node* merge(node* v, node* u) { if (!u) return v; if (!v) return u; push(v); push(u); if (v->prior > u->prior) return attach(v, v->L, merge(v->R, u)); else return attach(u, merge(v, u->L), u->R); } pair split_size(node* v, int k) { // (prefix of size k, rest) if (!v) return mp(v, v); int lewo = v->L ? v->L->sub : 0; push(v); if (lewo >= k) { auto s = split_size(v->L, k); return mp(s.st, attach(v, s.nd, v->R)); } else { auto s = split_size(v->R, k - lewo - 1); return mp(attach(v, v->L, s.st), s.nd); } } pair split_lex(node *v, PII k) { // (elements with values <= k, rest) if (!v) return mp(v, v); if (k < v->ind) { auto s = split_lex(v->L, k); return mp(s.st, attach(v, s.nd, v->R)); } else { auto s = split_lex(v->R, k); return mp(attach(v, v->L, s.st), s.nd); } } // int find_pos(node *v, PII val) { // -1 jesli nie ma // if (!v) return -1; // int lewo = v->L ? v->L->sub : 0; // if (v->ind == val) return 1 + lewo; // if (val < v->ind) return find_pos(v->L, val); // else return 1 + lewo + find_pos(v->R, val); // } const int N = 1e5 + 7; int n, m, q; int a[N]; int b[N]; Splay v[N]; int e[N]; void add(int ind) { v[a[ind]].make_root(); v[a[ind]].link(&v[b[ind]]); } void del(int ind) { v[b[ind]].make_root(); v[a[ind]].cut(); } bool ok(int ind) { return v[a[ind]].root() != v[b[ind]].root(); } ll sum(ll l, ll r) { if (l == 0 || l == 1) return r * (r + 1) / 2; else return r * (r + 1) / 2 - l * (l - 1) / 2; } int32_t main() { ios_base::sync_with_stdio(0); cin.tie(NULL); cin >> n >> m; for (int i = 1; i <= m; ++i) { cin >> a[i] >> b[i]; } int r = 0; for (int l = 1; l <= m; ++l) { while (r + 1 <= m && ok(r + 1)) { add(r + 1); ++r; } e[l] = r; debug(l, r); del(l); } node* root = 0; for (int i = 1; i <= m; ++i) { root = merge(root, new node(mp(e[i], i))); // root = merge(root, &t[i]); } cin >> q; while (q--) { int l, r; cin >> l >> r; auto s1 = split_size(root, r); auto s2 = split_size(s1.st, l - 1); auto seg = s2.nd; auto less = split_lex(seg, mp(r, -inf)); ll sum_r = (less.st ? less.st->sum : 0) + (ll)r * (less.nd? less.nd->sub : 0); ll sum_l = sum(l - 1, r - 1); cout << sum_r - sum_l << endl; s2.nd = merge(less.st, less.nd); s1.st = merge(s2.st, s2.nd); root = merge(s1.st, s1.nd); } }