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) {//旋转到所在splay的根
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) {//把原树上 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) {//返回 x 所在原树的根,并把原树的根旋转到辅助树的根
Access (x), splay (x);
while (ls (x)) Push_Down (x), x = ls (x);
return splay (x), x;
}
void Make_Root (int x) {//把 x 变为原树的根,并且旋转到辅助树的根
Access (x);
splay (x);
Change_Rev (x);
}
void Link (int x, int y) {//建一条 (x, y)
Make_Root (x);
if (Find_Root (y) != x) fa (x) = y; //不在一棵树内
}
void Cut (int x, int y) {//把 (x, 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) {//取出 x, y 的链,并且把 y 作为辅助树和原树的根
Make_Root (y), Access (x), splay (y), Push_Up (y);
}
};
LCT 模板
于 2022-03-11 21:11:22 首次发布