const int MaxLct = 2 * 1e5;
#define ls(p) (Tr[p].ch[0])
#define rs(p) (Tr[p].ch[1])
#define fa(p) (Tr[p].fa)
#define rev(p) (Tr[p].rev)
struct Node {
int rev;
int ch[2], fa;
};
struct Link_Cut_Tree {
Node Tr[MaxLct + 5];
int st[MaxLct + 5];
bool is_root (int p) { return (fa (p) == 0 || (ls (fa (p)) != p && rs (fa (p)) != p)); }
void Change_Rev (int p) {
if (!p) return;
rev (p) ^= 1; swap (ls (p), rs (p));
}
void Push_Down (int p) {
if (rev (p)) {
Change_Rev (ls (p)); Change_Rev (rs (p));
rev (p) = 0;
}
}
void Push_Up (int p) {
if (!p) return;
Push_Down (p);
}
void Rotate (int x) {
int y = fa (x), z = fa (y);
int d = rs (y) == x;
if (!is_root (y)) Tr[z].ch[Tr[z].ch[1] == y] = x; Tr[x].fa = z;
Tr[y].ch[d] = Tr[x].ch[!d]; if (Tr[x].ch[!d]) Tr[Tr[x].ch[!d]].fa = y;
Tr[x].ch[!d] = y; Tr[y].fa = x;
Push_Up (y); Push_Up (z);
}
void splay (int x) {
int y = x, z, tp = 0;
st[++tp] = y;
while (!is_root (y)) y = fa (y), st[++tp] = y;
while (tp) Push_Down (st[tp--]);
while (!is_root (x)) {
y = fa (x), z = fa (y);
if (!is_root (y)) {
if ((rs (z) == y) ^ (rs (y) == x)) Rotate (x);
else Rotate (y);
}
Rotate (x);
}
}
void Access (int x) {
int y = x; x = 0;
for (; y != 0; x = y, y = fa (y)) {
splay (y);
rs (y) = x;
Push_Up (y);
}
}
int Find_Root (int x) {
Access (x), splay (x);
while (ls (x)) Push_Down (x), x = ls (x);
return splay (x), x;
}
void Make_Root (int x) {
Access (x);
splay (x);
Change_Rev (x);
}
void Link (int x, int y) {
Make_Root (x);
if (Find_Root (y) != x) fa (x) = y;
}
void Cut (int x, int y) {
Make_Root (x);
Access (y), splay (y);
if (Find_Root (y) == x && fa (y) == x && !ls (y))
fa (y) = rs (x) = 0, Push_Up (x);
}
void Get (int x, int y) {
Make_Root (y), Access (x), splay (y), Push_Up (y);
}
};
|