博客
关于我
【LCT】P2147 [SDOI2008]洞穴勘测
阅读量:293 次
发布时间:2019-03-03

本文共 3125 字,大约阅读时间需要 10 分钟。

LCT(链接集合树)是一种高效的数据结构,广泛应用于处理各种树状结构的操作问题。以下是基于LCT的实现代码解析与应用示例。

代码结构分析:

  • 数据结构定义

    • 使用二叉树结构表示节点,每个节点包含父指针、左右子树指针以及逆序标记。
    • 树的大小限制为maxn,每个节点初始化时父指针、左右子树指针以及逆序标记都初始化为0。
  • 操作函数

    • isroot:判断一个节点是否为根节点。
    • rev:交换子树方向,并翻转逆序标记。
    • pushdown:将当前节点的子树操作下放到子节点。
    • rotate:旋转节点,使其成为新的根节点。
    • splay:通过旋转操作使树深度减少,提高操作效率。
    • access:通过路径压缩找到目标节点。
    • makeroot:将某个节点设置为根节点,并进行逆序调整。
    • findroot:找到当前树的根节点。
    • link:将两个树连接,形成新的树结构。
    • cut:将两个树分开,确保无环。
  • 代码应用示例:

    #include 
    using 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/

    你可能感兴趣的文章
    Node Sass does not yet support your current environment: Windows 64-bit with Unsupported runtime(72)
    查看>>
    Node 裁切图片的方法
    查看>>
    Node+Express连接mysql实现增删改查
    查看>>
    node, nvm, npm,pnpm,以前简单的前端环境为什么越来越复杂
    查看>>
    Node-RED中Button按钮组件和TextInput文字输入组件的使用
    查看>>
    Node-RED中Switch开关和Dropdown选择组件的使用
    查看>>
    Node-RED中使用html节点爬取HTML网页资料之爬取Node-RED的最新版本
    查看>>
    Node-RED中使用JSON数据建立web网站
    查看>>
    Node-RED中使用json节点解析JSON数据
    查看>>
    Node-RED中使用node-random节点来实现随机数在折线图中显示
    查看>>
    Node-RED中使用node-red-browser-utils节点实现选择Windows操作系统中的文件并实现图片预览
    查看>>
    Node-RED中使用node-red-contrib-image-output节点实现图片预览
    查看>>
    Node-RED中使用node-red-node-ui-iframe节点实现内嵌iframe访问其他网站的效果
    查看>>
    Node-RED中使用Notification元件显示警告讯息框(温度过高提示)
    查看>>
    Node-RED中使用range范围节点实现从一个范围对应至另一个范围
    查看>>
    Node-RED中实现HTML表单提交和获取提交的内容
    查看>>
    Node-RED中将CSV数据写入txt文件并从文件中读取解析数据
    查看>>
    Node-RED中建立TCP服务端和客户端
    查看>>
    Node-RED中建立Websocket客户端连接
    查看>>
    Node-RED中解析高德地图天气api的json数据显示天气仪表盘
    查看>>