1+ // https://codeforces.com/gym/104713/problem/K
2+ #include < bits/stdc++.h>
3+ using namespace std ;
4+
5+ #define forn (i,n ) for (int i=0 ; i<n; ++i)
6+ #define fi first
7+ #define se second
8+ #define el ' \n '
9+ #define d (x ) cout << #x << " : " << x<< el;
10+
11+ typedef pair<int , int > ii;
12+ typedef long long ll;
13+ typedef vector<int > vi;
14+ typedef vector<ll> vll;
15+ typedef vector<ii> vii;
16+
17+ struct Node { // Splay tree. Root's pp contains tree's parent.
18+ Node *p = 0 , *pp = 0 , *c[2 ] = {0 , 0 };
19+ bool flip = 0 ;
20+ Node (){}
21+ void fix () { forn (i, 2 ) if (c[i]) c[i]->p = this ; }
22+ inline int up () { return p ? p->c [1 ] == this : -1 ; }
23+ void push () {
24+ if (!flip) return ;
25+ flip = 0 , swap (c[0 ], c[1 ]);
26+ forn (i, 2 ) if (c[i]) c[i]->flip ^= 1 ;
27+ }
28+ void rot (int i, int b) {
29+ int h = i ^ b;
30+ Node *x = c[i], *y = b == 2 ? x : x->c [h], *z = b ? y : x;
31+ if ((y->p = p)) p->c [up ()] = y;
32+ c[i] = z->c [i^1 ];
33+ if (b < 2 ) x->c [h] = y->c [h^1 ], z->c [h^1 ] = b ? x : this ;
34+ y->c [i^1 ] = b ? this : x;
35+ fix (), x->fix (), y->fix ();
36+ if (p) p->fix ();
37+ swap (pp, y->pp );
38+ }
39+ void splay () { // Splay *this up to the root. Finishes without flip set.
40+ for (push (); p; ) {
41+ if (p->p ) p->p ->push ();
42+ p->push (), push ();
43+ int c1 = up (), c2 = p->up ();
44+ if (c2 == -1 ) p->rot (c1, 2 );
45+ else p->p ->rot (c2, c1 != c2);
46+ }
47+ }
48+ Node* first () { return push (), c[0 ] ? c[0 ]->first () : (splay (), this ); }
49+ }; // Return the MIN of the subtree rooted at this, splayed to the top.
50+
51+ struct LinkCut {
52+ vector<Node> node;
53+ LinkCut (int n) : node(n) {}
54+ Node* get (Node* u) { // / Move u to root aux tree.
55+ u->splay ();
56+ while (Node* pp = u->pp ) {
57+ pp->splay (), u->pp = 0 ;
58+ if (pp->c [1 ]) pp->c [1 ]->p = 0 , pp->c [1 ]->pp = pp;
59+ pp->c [1 ] = u, pp->fix (), u = pp;
60+ }
61+ return u; // Return the root of the root aux tree.
62+ }
63+ bool connected (int u, int v) { // are u, v in the same tree?
64+ return get (&node[u])->first () == get (&node[v])->first ();
65+ }
66+ void link (int u, int v) { // add an edge (u, v)
67+ assert (!connected (u, v)), makeRoot (&node[u]), node[u].pp = &node[v];
68+ }
69+ void cut (int u, int v) { // remove an edge (u, v)
70+ Node *x = &node[u], *top = &node[v];
71+ makeRoot (top), x->splay (), assert (top == (x->pp ? : x->c [0 ]));
72+ if (x->pp ) x->pp = 0 ;
73+ else x->c [0 ] = top->p = 0 , x->fix ();
74+ }
75+ void makeRoot (Node* u) { // / Move u to root of represented tree.
76+ get (u), u->splay ();
77+ if (u->c [0 ]) {
78+ u->c [0 ]->p = 0 ;
79+ u->c [0 ]->flip ^= 1 ;
80+ u->c [0 ]->pp = u;
81+ u->c [0 ] = 0 , u->fix ();
82+ }
83+ }
84+ };
85+
86+ ll gauss (int n){ return ll (n) * (n+1 ) / 2 ; }
87+
88+ int main (){
89+ ios_base::sync_with_stdio (0 ); cin.tie (0 );
90+ int n, m; cin >> n >> m;
91+ vii edges (m);
92+ forn (i, m){
93+ int u, v; cin >> u >> v;
94+ edges[i] = {--u, --v};
95+ }
96+
97+ vi R (m, m);
98+ LinkCut lc (n);
99+ int r = 0 ;
100+ forn (l, m){
101+ while (r < m && !lc.connected (edges[r].fi , edges[r].se )){
102+ lc.link (edges[r].fi , edges[r].se ), ++r;
103+ }
104+ R[l] = r;
105+ lc.cut (edges[l].fi , edges[l].se );
106+ }
107+ vll pR (m); ll sum = 0 ;
108+ forn (i, m) pR[i] = sum += (R[i] - i);
109+
110+ int q; cin >> q;
111+ forn (_, q){
112+ int l, r; cin >> l >> r; --l, --r;
113+ if (R[l] > r+1 ) cout << gauss (r - l + 1 ) << el;
114+ else {
115+ int bl = l, br = r; // (1, 0)
116+ while (bl+1 < br){
117+ int bm = (bl + br) / 2 ;
118+ if (R[bm] <= r+1 ) bl = bm;
119+ else br = bm;
120+ }
121+ cout << pR[bl] - (l ? pR[l-1 ] : 0 ) + gauss (r - bl) << el;
122+ }
123+ }
124+ }
0 commit comments