-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathlink_cut_tree.cpp
118 lines (116 loc) · 3.4 KB
/
link_cut_tree.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
115
116
117
118
//太长了,压缩一下
#include <cstdio>
#include <algorithm>
const int N = 400010;
const int inf = ~0u >> 2;
struct Node* null;
struct Node
{
Node* ch[2];
Node* fa;
int mi, val, rev;
inline int sgn(){return fa->ch[0]==this?0:fa->ch[1]==this?1:-1;}
inline void setc(int s, Node* who){who->fa=this;ch[s]=who;}
inline void rotate() {
int a=sgn(),b=fa->sgn();
Node* y=fa; y->setc(a,ch[!a]),fa=y->fa;
if(~b) fa->ch[b]=this;
this->setc(!a,y),y->up();
}
inline void splay() {
go();
for(int a,b;~(a=sgn());rotate())
if(~(b=fa->sgn()))
(a^b)?rotate():fa->rotate();
up();
}
inline void up() {
mi = std::min(ch[0]->mi, ch[1]->mi);
mi = std::min(mi, val);
}
void init(int v, Node* f) {
fa = f;
val = mi = v;
ch[0] = ch[1] = null;
rev = 0;
}
void flip() {
std::swap(ch[0], ch[1]);
rev ^= 1;
}
void push() {
if(rev) {
ch[0]->flip(), ch[1]->flip(), rev = 0;
}
}
void print() {
if(this != null) {
if(ch[0] != null) ch[0]->print();
printf("%d\n", val);
if(ch[1] != null) ch[1]->print();
}
}
void go() {
if(~sgn()) fa->go();
push();
}
};
struct Link_Cut_Tree
{
Node node[N];
Node* access(Node* u) {
Node* v = null;
for(; u != null; v = u, u = u->fa) {
u->splay();
u->ch[1] = v;
u->up();
}
return v;
}
int ask(Node* x, Node* y) {
access(x);
for(x = null; y != null; y = y->fa) {
y->splay();
if(y->fa == null) {
return std::min(y->ch[1]->mi, x->mi);
}
y->ch[1] = x, y->up(), x = y;
}
}
int ask(int a, int b) {
return ask(node + a, node + b);
}
void cut(int v) {
Node* u = node + v;
access(u);
u->splay();
u->ch[0]->fa = null;
u->ch[0] = null;
u->up();
}
//切掉u跟v之间的边
void cut(Node* u, Node* v) {
access(u), v->splay();
if(v->fa == u) {
v->fa = null;
} else {
access(v), u->splay(), u->fa = null;
}
}
//连接u跟v之间的边
void link(Node* u, Node* v) {
make_root(u);
u->fa = v;
}
//将u变成树根
void make_root(Node* u) {
Node* tmp = access(u);
tmp->flip();
u->splay();
}
bool judge(Node* u, Node* v) {
while(u->fa != null) u = u->fa;
while(v->fa != null) v = v->fa;
return u == v;
}
}lct;