可以按照<Utopiosphere>的调唱出来 “Link-Cut ,Time doesn’t stop .Prepare your doubts ,Eat them up”

参考资料:

1.popoqqq课件

2.《QTREE 解法的一些研究 》

3.http://blog.csdn.net/clove_unique/article/details/50991804

一【理论知识】

  • Link-Cut-Tree(简称LCT)是解决动态树类问题一种数据结构
  • Preferred Child:重儿子,重儿子与父亲节点在同一棵Splay中,一个节点最多只能有一个重儿子
  • Preferred Edge:重边,连接父亲节点和重儿子的边
  • Preferred Path :重链,由重边及重边连接的节点构成的链

Auxiliary Tree(辅助树)

  • 由一条重链上的所有节点所构成的Splay称作这条链的辅助树
  • 每个点的键值为这个点的深度,即这棵Splay的中序遍历是这条链从链顶到链底的所有节点构成的序列
  • 辅助树的根节点的父亲指向链顶的父亲节点,然而链顶的父亲节点的儿子并不指向辅助树的根节点
  • (也就是说父亲不认轻儿子只认重儿子,儿子都认父亲)
  • 这条性质为后来的操作提供了依据

原树与辅助树的关系

  • 原树中的重链 -> 辅助树中两个节点位于同一棵Splay
  • 原树中的轻链 -> 辅助树中子节点所在Splay的根节点的father指向父节点
  • 注意原树与辅助树的结构并不相同
  • 辅助树的根节点≠原树的根节点
  • 辅助树中的father≠原树中的father

辅助树是不断变化的,重链和轻链不断变化

二【实现】

LCT用到的Splay和通常的还是有点不同,没有权值v,不进行查找操作,点编号就是原树的编号

因为是一个Splay森林,多条重链多个根,所以用isRoot(x)判断是否为根,判断isRoot(x)相当于判断x的父亲存不存在

rotate只是设置g的儿子时判断isRoot(f)就行了

splay需要pushDown了(因为没有kth了),也是判断isRoot(pa)

Access和Cut更新了儿子关系,所以需要update

Access

  • 将一个点与原先的重儿子切断,并使这个原树上点到根路径上的边全都变为重边
  • 所以 这个节点到根的路径上的所有节点形成了一棵Splay
  • 便于操作或查询节点到根路径上的所有节点

实现:不断把x splay到当前Atree的根,然后它的右子树就是重儿子了,修改;用y辅助

注意:Access后x不一定为这颗Splay的根,因为中途x变fa了

维护了节点信息别忘更新

MakeRoot

  • 将x设为原树的根

实现:Access后splay到根,然后全在x的左子树上(权值是深度),区间翻转即可

FindRoot

  • 找x所在原树根,判连通性

实现:MakeRoot后不断往左找(不需要pushDown?加上也可以啊。不加也对因为只是来判连通,判断是不是在一棵原树上,都不pushDown找到的还是同一个点吧)

Link

实现:MakeRoot(x)然后t[x].fa=y

Cut

实现:MakeRoot(x)然后Access(y) splay(y) ,x就在y的左儿子了,t[y].ch[0]=t[x].fa=0;

维护了节点信息别忘更新

对x到y路径上的点进行修改或查询
只需要对x进行Move_To_Root操作,然后对y进行Access+Splay操作,那么x到y路径上的所有点都在以y为根的子树上

因为Access后x和y重链在一棵Splay上,x深度比y小

三【模板】

[update 2017-04-05]

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define lc t[x].ch[0]
#define rc t[x].ch[1]
#define pa t[x].fa
typedef long long ll;
const int N=3e5+;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
} namespace lct {
struct meow{int ch[], fa, rev, sum, w;} t[N];
inline int wh(int x) {return t[pa].ch[] == x;}
inline int isr(int x) {return t[pa].ch[] != x && t[pa].ch[] != x;}
inline void update(int x) {t[x].sum = t[lc].sum ^ t[rc].sum ^ t[x].w;}
inline void rever(int x) {t[x].rev ^= ; swap(lc, rc);}
inline void pushdn(int x) {
if(t[x].rev) {
if(lc) rever(lc);
if(rc) rever(rc);
t[x].rev = ;
}
}
void pd(int x) {if(!isr(x)) pd(pa); pushdn(x);}
inline void rotate(int x) {
int f=t[x].fa, g=t[f].fa, c=wh(x);
if(!isr(f)) t[g].ch[wh(f)]=x; t[x].fa=g;
t[f].ch[c] = t[x].ch[c^]; t[t[f].ch[c]].fa=f;
t[x].ch[c^] = f; t[f].fa=x;
update(f); update(x);
}
inline void splay(int x) {
pd(x);
for(; !isr(x); rotate(x))
if(!isr(pa)) rotate( wh(pa)==wh(x) ? pa : x );
} inline void access(int x) {
for(int y=; x; y=x, x=pa) splay(x), rc=y, update(x);
}
inline void maker(int x) {
access(x); splay(x); rever(x);
}
inline int findr(int x) {
access(x); splay(x);
while(lc) pushdn(x), x=lc; return x;
}
inline void link(int x, int y) {
maker(x); t[x].fa=y;
}
inline void cut(int x, int y) {
maker(x); access(y); splay(y);
t[x].fa = t[y].ch[] = ; update(y);
}
inline void split(int x, int y) {
maker(x); access(y); splay(y);
}
} using lct::findr; int n, Q, op, x, y;
int main() {
freopen("in","r",stdin);
n=read(); Q=read();
for(int i=; i<=n; i++) lct::t[i].w = read();
for(int i=; i<=Q; i++) {
op=read(); x=read(); y=read();
if(op==) lct::split(x, y), printf("%d\n", lct::t[y].sum);
if(op==) if(findr(x) != findr(y)) lct::link(x, y);
if(op==) if(findr(x) == findr(y)) lct::cut(x, y);
if(op==) lct::t[x].w = y, lct::splay(x);
}
}

四【一点好玩的东西】

1.LCT可做动态树问题

2.LCT可做树链剖分

3.LCT可做支持删除边的并查集(我太navie了.......并不能完全实现这个功能,是一颗树啊啊啊)

4.LCT可做不用排序的Kruskal(动态加边的最小生成树)

[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. 微信小程序路过

    应该算是入门篇, 从我怎么0基础然后沿着什么方向走,遇到的什么坑,如何方向解决,不过本人接触不是很多,所以也就了解有限. 小程序的前提: 1.小程序大小不允许超过2M.(也就是本地图片,大图精图不要在 ...

  2. Sagit.Framework For IOS 开发框架入门教程4:注册页布局-被消灭的变量

    前言: 上篇写完:Sagit.Framework For IOS 开发框架入门教程3:Start引导页-框架布局和隐藏事件的内幕 之后,好久没写文章了,有IT连创业系列.有DotNetCore的一篇文 ...

  3. 查看Flink的Job Graph时的问题

    Flink运行Job时,可以通过Job Graph看到执行计划,但是如果用IE,会被坑: 换成谷歌Chrome,就OK了: 这个Job Grap,好像是SVG的,可能是IE不支持SVG,需要安装插件才 ...

  4. iOS 字体设置,字体类型展示

    字体设置: [UIFont fontWithName:@"Helvetica" size:17.0]]; 字体名字,如图 UIFont fontWithName 后不知道字体的名字 ...

  5. php date函数

    PHP星期几获取代码: 1 date("l"); 2 //data就可以获取英文的星期比如Sunday 3 date("w"); 4 //这个可以获取数字星期比 ...

  6. Docker(十):Docker安全

    1.Docker安全主要体现在如下方面 a)Docker容器的安全性 b)镜像安全性 c)Docker daemon安全性 2.安装策略 2.1 Cgroup Cgroup用于限制容器对CPU.内存的 ...

  7. iOS音频采集过程中的音效实现

    1.背景 在移动直播中, 声音是主播和观众互动的重要途径之一, 为了丰富直播的内容,大家都会想要在声音上做一些文章, 在采集录音的基础上玩一些花样. 比如演唱类的直播间中, 主播伴随着背景音乐演唱. ...

  8. oracle12c_安装3——部署

    数据库安装后需要根据实际情况修改相关参数. 1.生成pfile以防万一. SQL> create pfile from spfile; 2.修改内存参数 只要设置MEMORY_MAX_TARGE ...

  9. Mobiscroll的介绍【一款兼容PC和移动设备的滑动插件】

    Mobiscroll是一个用于触摸设备的日期和时间选择器,它的使用不会改变HTML5.PhoneGap以及混合应用的原生用户体验.作为一款jQuery滑动选择插件,用户可以自定义主题样式,为自己的移动 ...

  10. Head First设计模式之工厂模式

    一.定义 定义了一个创建对象的接口, 但由子类决定要实例化的类是哪一个. 工厂方法让类把实例化推迟到子类 二.结构 1.抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关.是具体工厂角色必须实现的 ...