Link-cut Tree是一种支持改变树(森林)的形态(link和cut),同时维护树的路径上节点信息的数据结构。lct通过splay来维护每次的perferred path,说白了就是一个动态的树链剖分。splay的左右儿子分别代表preferred path上深度比它小和深度比它大的节点。

Link-cut Tree需要支持以下的操作:

1.access(x): 将节点x连接到perferred path上,返回值是一个节点,如果这是第一次access,则返回根节点,如果之前还access其他节点,则返回lca(last, x)。
2.makeroot(x): 将x这个节点作为根,也就是换根操作。
3.link(x,y): 连接x和y所在的子树。
4.cut(x,y): 将x和y之间的边删除。

我们先来看看access操作,借用Yang Zhe大神论文里的一张图来对access操作有一个形象的理解:

这一次access过后,从N到根的路径都变成了perferred path。

然后我们再来看看makeroot操作,我们单次makeroot操作就是把需要作为根的节点access,然后splay再到顶端,再通过给这个节点打上rev标记来将左右儿子交换。(不理解的可以画一张图理解一下。)
这下有了makeroot也有了access,就很容易地处理出一条链上的信息了,link就只要makeroot(a),fa[a]=b就好了,cut只要makeroot(a),access(b),splay(a),ch[a][0]=fa[b]=0就能解决。

参考模板:

//
// Title : LCT(change root)
// Date : 03.05.2016
// Test : BZOJ-2049
// Complexity : O(mlogn)
//
/*
对于有link和cut操作维护树上的信息等问题——
解决办法:link-cut tree
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath> #ifdef WIN32
#define LL "%I64d"
#else
#define LL "%lld"
#endif #ifdef CT
#define debug(...) printf(__VA_ARGS__)
#define setfile()
#else
#define debug(...)
#define filename ""
#define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout);
#endif #define R register
#define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++)
#define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
#define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
#define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
char B[1 << 15], *S = B, *T = B;
inline int FastIn()
{
R char ch; R int cnt = 0; R bool minus = 0;
while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ;
ch == '-' ? minus = 1 : cnt = ch - '0';
while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
return minus ? -cnt : cnt;
}
#define maxn 200010
int n, m;
struct Node *null;
struct Node
{
bool rev;
Node *ch[2], *fa;
inline bool type()
{
return fa -> ch[1] == this;
}
inline bool check()
{
return this == fa -> ch[type()];
}
inline void set_rev()
{
std::swap(ch[0], ch[1]);
rev ^= 1;
}
inline void pushdown()
{
if (rev)
{
ch[0] -> set_rev();
ch[1] -> set_rev();
rev = 0;
}
}
void pushdownall()
{
if (check())
fa -> pushdownall();
pushdown();
}
inline void rotate()
{
R Node *f = fa;
R bool d = type();
(fa = f -> fa), f -> check() ? fa -> ch[f -> type()] = this : 0;
(f -> ch[d] = ch[!d]) != null ? ch[!d] -> fa = f : 0;
(ch[!d] = f) -> fa = this;
}
inline void splay(R bool need = 1)
{
if (need) pushdownall();
for (; check(); rotate())
if (fa -> check())
(type() != fa -> type() ? this : fa) -> rotate();
}
inline Node *access()
{
R Node *i = this, *j = null;
for (; i != null; i = (j = i) -> fa)
{
i -> splay();
i -> ch[1] = j;
}
return j;
}
inline void make_root()
{
access();
splay(0);
set_rev();
}
inline void link(R Node *that)
{
make_root();
fa = that;
}
inline void cut(R Node *that)
{
make_root();
that -> access();
splay(0);
that -> fa = ch[1] = null;
}
inline bool find(R Node *that)
{
access();
splay();
while (that -> fa != null)
that = that -> fa;
return that == this;
}
}mem[maxn];
int main()
{
// setfile();
n = FastIn(), m = FastIn();
null = mem;
null -> fa = null -> ch[0] = null -> ch[1] = null;
for (R int i = 1; i <= n; ++i) mem[i] = (Node) {0, {null, null}, null};
for (R int i = 1; i <= m; ++i)
{
R char opt;
while (opt = getc(), opt < 'A' || opt > 'Z');
R int a = FastIn(), b = FastIn();
if (opt == 'C')
{
(mem + a) -> link(mem + b);
}
else if (opt == 'D')
{
(mem + a) -> cut(mem + b);
}
else
{
puts((mem + a) -> find(mem + b) ? "Yes" : "No");
}
}
return 0;
}

练习建议:
BZOJ2002 [Hnoi2010]Bounce 弹飞绵羊
BZOJ2049 [Sdoi2008]Cave 洞穴勘测
BZOJ3282 Tree

【学习心得】Link-cut Tree的更多相关文章

  1. Link Cut Tree学习笔记

    从这里开始 动态树问题和Link Cut Tree 一些定义 access操作 换根操作 link和cut操作 时间复杂度证明 Link Cut Tree维护链上信息 Link Cut Tree维护子 ...

  2. 学习笔记:Link Cut Tree

    模板题 原理 类似树链剖分对重儿子/长儿子剖分,Link Cut Tree 也做的是类似的链剖分. 每个节点选出 \(0 / 1\) 个儿子作为实儿子,剩下是虚儿子.对应的边是实边/虚边,虚实时可以进 ...

  3. link cut tree 入门

    鉴于最近写bzoj还有51nod都出现写不动的现象,决定学习一波厉害的算法/数据结构. link cut tree:研究popoqqq那个神ppt. bzoj1036:维护access操作就可以了. ...

  4. LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)

    为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...

  5. Codeforces Round #339 (Div. 2) A. Link/Cut Tree 水题

    A. Link/Cut Tree 题目连接: http://www.codeforces.com/contest/614/problem/A Description Programmer Rostis ...

  6. Link/cut Tree

    Link/cut Tree 一棵link/cut tree是一种用以表示一个森林,一个有根树集合的数据结构.它提供以下操作: 向森林中加入一棵只有一个点的树. 将一个点及其子树从其所在的树上断开. 将 ...

  7. 洛谷P3690 Link Cut Tree (模板)

    Link Cut Tree 刚开始写了个指针版..调了一天然后放弃了.. 最后还是学了黄学长的板子!! #include <bits/stdc++.h> #define INF 0x3f3 ...

  8. bzoj2049 [Sdoi2008]Cave 洞穴勘测 link cut tree入门

    link cut tree入门题 首先说明本人只会写自底向上的数组版(都说了不写指针.不写自顶向下QAQ……) 突然发现link cut tree不难写... 说一下各个函数作用: bool isro ...

  9. P3690 【模板】Link Cut Tree (动态树)

    P3690 [模板]Link Cut Tree (动态树) 认父不认子的lct 注意:不 要 把 $fa[x]$和$nrt(x)$ 混 在 一 起 ! #include<cstdio> v ...

  10. [CodeForces - 614A] A - Link/Cut Tree

    A - Link/Cut Tree Programmer Rostislav got seriously interested in the Link/Cut Tree data structure, ...

随机推荐

  1. CentOS 7.3下使用yum安装MySQL

    CentOS 7的yum源中默认是没有mysql的,要先下载mysql的repo源. 1.下载mysql的repo源 $ wget http://repo.mysql.com/mysql-commun ...

  2. 【HANA系列】SAP HANA ODBC error due to mismatch of version

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA ODBC er ...

  3. ARP协议基础

    ARP 什么是ARP协议 ARP协议是能够根据IP地址解析出该IP地址所在设备的MAC地址,叫(Address Resolution Protocol)地址解析协议 ARP地址的工作流程 当一台主机A ...

  4. MVC中的cshtml与ASPX的区别

    在MVC3中,即可以使用cshtml,也可以使用aspx, 这两者到底有什么区别呢? 越详细越好,如果是用来正式开发,用哪种比较好. --------------------------------- ...

  5. Java基础语法—流程控制语句

    在一个程序执行的过程中,各条语句的执行顺序对程序的结果是有直接影响的.所以,我们必须清楚每条语句的执行流程.而且,很多时候要通过控制语句的执行顺序来实现我们想要的功能. 3.1 流程控制语句分类 ​ ...

  6. 如何查看SQL Server某个存储过程的执行历史【转】

    db_name(d.database_id) as DBName, s.name as 存储名称, s.type_desc as 存储类型, d.cached_time as SP添加到缓存的时间, ...

  7. PHP排序函数sort、rsort、asort、arsort、ksort、krsort

    1.sort函数用于对数组元素值从低到高排序,去除原始索引元素,重新生成0,1,2..的键2.rsort函数用于对数组元素值从高到低排序,去除原始索引元素,重新生成0,1,2..的键3.asort函数 ...

  8. 1、Java语言概述与开发环境——Java程序运行机制

    Java语言是一种特殊的高级语言,它既有解释型语言的特性,也具有编译型语言的特征,因为Java要经过先编译后解释两个步骤. 一.高级语言的运行机制 计算机高级语言按程序的执行方式可以分为编译型和解释型 ...

  9. python 发送kafka

    python 发送kafka大体有三种方式 1 发送并忘记(不关注是否正常到达,不对返回结果做处理) 1 import pickle 2 import time 3 from kafka import ...

  10. 根据日志来源的不同生成不同的index索引

    使用filebeat收集系统日志,不同应用的日志,然后把这些日志传输给Logstash,再然后交由elasticsearch处理,那么如何区分不同的日志来源呢? filebeat.yml配置文件中不启 ...