Link Cut Tree
Posted luckyblock
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Link Cut Tree相关的知识,希望对你有一定的参考价值。
//知识点 : LCT
/*
By:Luckyblock
*/
#include <cstdio>
#include <ctype.h>
#include <algorithm>
#define ls (t[x].son[0])
#define rs (t[x].son[1])
const int kMaxn = 1e5 + 10;
//=============================================================
struct Link_Cut_Tree_Node {
int son[2], fa;
int xr, rev;
} t[kMaxn];
int n, m, val[kMaxn], st[kMaxn];
//=============================================================
inline int read() {
int f = 1, w = 0; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == ‘-‘) f = -1;
for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ ‘0‘);
return f * w;
}
void Pushup(int x) {
t[x].xr = t[ls].xr ^ t[rs].xr ^ val[x];
}
void PushReverse(int x) {
std :: swap(ls, rs);
t[x].rev ^= 1;
}
void Pushdown(int x) {
if (! t[x].rev) return ;
if (ls) PushReverse(ls);
if (rs) PushReverse(rs);
t[x].rev = 0;
}
bool IsNotRoot(int x) {
return t[t[x].fa].son[0] == x || t[t[x].fa].son[1] == x;
}
int GetSonNum(int x) {
return t[t[x].fa].son[1] == x;
}
void Rotate(int x) {
int fa = t[x].fa, gfa = t[fa].fa, which_son = GetSonNum(x);
//注意旋转顺序,在splay中这句可放在最后,但在lct中不可。
//因为下面的两句改变了结构,无法判断原fa是否为根节点。
if (IsNotRoot(fa)) t[gfa].son[t[gfa].son[1] == fa] = x;
t[x].fa = gfa;
t[fa].son[which_son] = t[x].son[which_son ^ 1];
t[t[fa].son[which_son]].fa = fa;
t[x].son[which_son ^ 1] = fa;
t[fa].fa = x;
Pushup(fa);
}
void Splay(int x) {
int now = x, cnt = 0;
st[++ cnt] = now;
while (IsNotRoot(now)) st[++ cnt] = (now = t[now].fa);
while (cnt) Pushdown(st[cnt --]);
for (int y = t[x].fa; IsNotRoot(x); Rotate(x)) {
y = t[x].fa;
if (IsNotRoot(y)) Rotate(GetSonNum(x) == GetSonNum(y) ? y : x);
}
Pushup(x);
}
void Access(int x) {
for (int y = 0; x; y = x, x = t[x].fa) {
Splay(x), rs = y;
Pushup(x);
}
}
void MakeRoot(int x) {
Access(x);
Splay(x);
PushReverse(x);
}
int FindRoot(int x) {
Access(x); Splay(x);
while (ls) Pushdown(x), x = ls;
Splay(x);
return x;
}
void Split(int x, int y) {
MakeRoot(x);
Access(y);
Splay(y);
}
void Cut(int x, int y) {
MakeRoot(x);
if(FindRoot(y) != x || t[y].fa != x || t[y].son[0]) return ;
t[y].fa = t[x].son[1] = 0;
Pushup(x);
}
void Link(int x, int y) {
MakeRoot(x);
if(FindRoot(y) != x) t[x].fa = y;
}
//=============================================================
int main() {
n = read(), m = read();
for (int i = 1; i <= n; ++ i) {
t[i].xr = val[i] = read();
}
for (int i = 1; i <= m; ++ i) {
int opt = read(), x = read(), y = read();
if (opt == 0) {
Split(x, y);
printf("%d
", t[y].xr);
}
if (opt == 1) Link(x, y);
if (opt == 2) Cut(x, y);
if (opt == 3) {
Splay(x);
val[x] = y;
}
}
return 0;
}
以上是关于Link Cut Tree的主要内容,如果未能解决你的问题,请参考以下文章
题解 luogu P1501[国家集训队]Tree II(Link-Cut-Tree)
luogu3690 模板Link Cut Tree (动态树)