-
Notifications
You must be signed in to change notification settings - Fork 9
/
lct.cpp
114 lines (93 loc) · 1.64 KB
/
lct.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// lct.cpp
// Eric K. Zhang; Nov. 22, 2017
#include <bits/stdc++.h>
using namespace std;
#define MAXN 100013
// Link-cut node
struct node {
node* p;
node* c[2];
int x, s;
bool flip;
bool r() { return !p || (p->c[0] != this && p->c[1] != this); }
int d() { return r() ? -1 : p->c[1] == this; }
void update() {
s = x + (c[0] ? c[0]->s : 0) + (c[1] ? c[1]->s : 0);
}
void push() {
if (flip) {
swap(c[0], c[1]);
if (c[0]) c[0]->flip ^= 1;
if (c[1]) c[1]->flip ^= 1;
flip = false;
}
}
static void connect(node* pa, node* ch, int dir) {
if (ch) ch->p = pa;
if (dir != -1) pa->c[dir] = ch;
}
void rot() {
assert(!r());
int x = d();
node* pa = p;
connect(pa->p, this, pa->d());
connect(pa, c[!x], x);
connect(this, pa, !x);
pa->update();
update();
}
void splay() {
while (!r() && !p->r()) {
p->p->push();
p->push();
push();
if (d() == p->d()) p->rot();
else rot();
rot();
}
if (!r()) {
p->push();
push();
rot();
}
push();
}
void expose() {
node* pre = nullptr;
for (node* v = this; v; v = v->p) {
v->splay();
v->c[1] = pre;
v->update();
pre = v;
}
splay();
}
void make_root() {
expose();
flip ^= 1;
}
} verts[MAXN];
inline node* n(int i) { return verts + i; }
node* find_root(node* x) {
x->expose();
while (x->c[0]) x = x->c[0];
x->splay();
return x;
}
bool connected(node* x, node* y) {
return find_root(x) == find_root(y);
}
void link(node* x, node* y) {
x->make_root();
x->p = y;
}
void upd(node* x, int amt) {
x->splay();
x->x = amt;
x->update();
}
int path_aggregate(node* x, node* y) {
x->make_root();
y->expose();
return y->s;
}