Skip to content

Commit fa61f1e

Browse files
committed
Add 2nd test Link Cut Tree
1 parent 43a7db5 commit fa61f1e

File tree

2 files changed

+124
-0
lines changed

2 files changed

+124
-0
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
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

Comments
 (0)