本文共 3125 字,大约阅读时间需要 10 分钟。
LCT(链接集合树)是一种高效的数据结构,广泛应用于处理各种树状结构的操作问题。以下是基于LCT的实现代码解析与应用示例。
代码结构分析:
数据结构定义:
maxn,每个节点初始化时父指针、左右子树指针以及逆序标记都初始化为0。操作函数:
isroot:判断一个节点是否为根节点。rev:交换子树方向,并翻转逆序标记。pushdown:将当前节点的子树操作下放到子节点。rotate:旋转节点,使其成为新的根节点。splay:通过旋转操作使树深度减少,提高操作效率。access:通过路径压缩找到目标节点。makeroot:将某个节点设置为根节点,并进行逆序调整。findroot:找到当前树的根节点。link:将两个树连接,形成新的树结构。cut:将两个树分开,确保无环。代码应用示例:
#includeusing namespace std;const int maxn = 2e5;int n, m;struct LCT { struct node { int fa, ch[2], rev; node() { fa = ch[0] = ch[1] = rev = 0; } } tree[maxn]; int top, res[maxn]; #define ls(x) tree[x].ch[0] #define rs(x) tree[x].ch[1] int isroot(int x) { return tree[x].fa && (ls(tree[x].fa) == x || rs(tree[x].fa) == x); } void rev(int x) { swap(ls(x), rs(x)); tree[x].rev ^= 1; } void pushdown(int x) { if (!tree[x].rev) return; if (ls(x)) rev(ls(x)); if (rs(x)) rev(rs(x)); tree[x].rev ^= 1; } void rotate(int x) { int y = tree[x].fa, z = tree[y].fa; int k = (x == ls(tree[x].fa)), w = tree[x].ch[k]; if (isroot(y)) tree[z].ch[y == rs(tree[y].fa)] = x; tree[x].ch[k] = y; tree[y].ch[!k] = w; tree[y].fa = x; tree[x].fa = z; if (w) tree[w].fa = y; } void splay(int x) { int tmp = x; res[top = 1] = tmp; while (isroot(tmp)) { res[++top] = tree[tmp].fa; tmp = tree[tmp].fa; } while (top) { pushdown(res[top]); top--; } while (isroot(x)) { if (isroot(tree[x].fa)) { int k = (x == rs(tree[x].fa)) ^ (tree[x].fa == rs(tree[tree[x].fa].fa)); rotate(k ? tree[x].fa : x); } rotate(x); } } void access(int x) { for (int y = 0; x; x = tree[x].fa) { splay(x); rs(x) = y; } } void makeroot(int x) { access(x); splay(x); rev(x); } int findroot(int x) { access(x); splay(x); while (ls(x)) { pushdown(x); x = ls(x); pushdown(x); } return x; } void link(int x, int y) { if (findroot(x) == findroot(y)) return; makeroot(x); tree[x].fa = y; } void cut(int x, int y) { makeroot(x); access(y); splay(y); if (ls(y) == x) { tree[x].fa = ls(y) = 0; } }} LCT;int main() { freopen("a.in", "r", stdin); freopen("a.out", "w", stdout); scanf("%d%d", &n, &m); char op[20]; int x, y; for (int i = 1; i <= m; ++i) { scanf("%s", op); scanf("%d%d", &x, &y); if (op[0] == 'C') { LCT.link(x, y); } else if (op[0] == 'D') { LCT.cut(x, y); } else if (op[0] == 'Q') { if (LCT.findroot(x) == LCT.findroot(y)) { printf("Yes\n"); } else { printf("No\n"); } } } return 0;}
以上代码实现了一个高效的LCT结构,支持常规的树操作,如连接、切割以及根节点查询等功能。通过路径压缩和旋转操作,LCT显著提升了树操作的效率,使得复杂度接近线性。
转载地址:http://idwm.baihongyu.com/