唔,其实我不会 Splay,但是我会 LCT。

众所周知,会 LCT 和会 Splay 是两回事,因为 LCT 只需要旋至根即可。

到现在还是不会,但是先把 LCT 的 Splay 写一下吧。

自己复习用的。

先给代码。

LCT code
int isroot(int x) {return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
int idt(int x) {return ch[fa[x]][1]==x;}
void swp(int x) {
if(!x) return ;
rev[x]^=1;
swap(ls,rs);
}
void pushdown(int x) {
if(rev[x]) {
rev[x]=0;
swp(ls);
swp(rs);
}
}
void pushup(int x) {
if(!x) return;
if(x<=n) ma[x]=-INF;
else ma[x]=val[x];
if(ls) cmax(ma[x],ma[ls]);
if(rs) cmax(ma[x],ma[rs]);
}
void pushall(int x) {
if(!isroot(x)) pushall(fa[x]);
pushdown(x);
}
void add(int y,int x,int i) {ch[fa[x]=y][i]=x;}
void rotate(int x) {
int y=fa[x],i=idt(x);
if(isroot(y)) fa[x]=fa[y];
else add(fa[y],x,idt(y));
add(y,ch[x][!i],i);
add(x,y,!i);
pushup(y);
}
void splay(int x) {
pushall(x);
for(int y;y=fa[x],!isroot(x);rotate(x)) {
if(!isroot(y)) rotate(idt(x)==idt(y)?y:x);
}
pushup(x);
}
void access(int x) {
for(int p=0;x;p=x,x=fa[x]) {
splay(x);
ch[x][1]=p;
pushup(x);
}
}
void makeroot(int x) {
access(x);
splay(x);
swp(x);
}
void split(int u,int v) {
makeroot(u);
access(v);
splay(u);
}
void cut(int u,int v) {
split(u,v);
ch[u][1]=fa[v]=0;
pushup(u);
}
int findroot(int x) {
access(x);
splay(x);
while(pushdown(x), ls) x = ls;
splay(x);
}

主要就是下面这三个函数。分开讨论。

\(rotate\) 操作说明

因为 y = fa[x],那么有 x = ch[y][i]

旋转的过程即是先用 \(x\) 替换 \(y\),即从 fa[y] 的视角而言。

然后用 \(x, y\) 两点间“包夹”的子树替换 \(x\),即从 \(y\) 的包夹子树的视角而言。

最后将子树的位置用 \(y\) 替换,即从 \(x\) 的视角而言。

\(splay\) 操作

这个主要是旋转方向的问题。

就是第一次有可能对父亲也有可能对自己,若自己与父亲呈一条线idt(y) == idt(x)则转父亲,此时是一个相对于 x <- fa[x] -> fa[fa[x]] 的较平衡形态 \(1\),否则转自己,此时是 fa[fa[x]]->x->fa[x] 的直线形态 \(2\)。

发现无论怎样都需要将 x 再次旋至根,若原来为 \(1\) 形态,旋转后会变成 x -> fa[x] - > fa[fa[x]] 的形态,若原来为 \(2\) 形态,则旋转后会变为 fa[fa[x]] <- x -> fa[x] 的较平衡形态。

对了,还有当前只有一层深度,此时只用旋转 x 即可。

那么这样的话无论怎样都会出现一次较平衡形态,所以可以保证复杂度。

当然,这样只是便于记忆罢了。

严谨的分析其实可以用势能分析法,OI-Wiki 上有,等我学成归来……

然后我们再分析只有单旋的,若开始前是直线状态,则单旋两次后不会出现较平衡形态,而是先出现一个折线,再出现一条直线。

若开始前为折线,则单旋两次后先出现一条直线,再出现一个较平衡状态。

是的,所以若开始前为直线则不能保证复杂度。

同样,这也不是严谨分析……

\(access\) 操作

将 \(x\) 与 原树上的根 之间的路径取出。

注意点:

  1. 操作完后 \(x\) 有实儿子,但是只会有左儿子,即原树的到根的链上的节点,所以得到的是一条从 根 到 \(x\) 的链,没有其他节点。

  2. pushup(x)

Splay/LCT 学习笔记的更多相关文章

  1. LCT 学习笔记

    LCT学习笔记 前言 自己定的学习计划看起来完不成了(两天没学东西,全在补题),决定赶快学点东西 于是就学LCT了 简介 Link/Cut Tree是一种数据结构,我们用它解决动态树问题 但是LCT不 ...

  2. BST,Splay平衡树学习笔记

    BST,Splay平衡树学习笔记 1.二叉查找树BST BST是一种二叉树形结构,其特点就在于:每一个非叶子结点的值都大于他的左子树中的任意一个值,并都小于他的右子树中的任意一个值. 2.BST的用处 ...

  3. SPLAY,LCT学习笔记(六)

    这应该暂时是个终结篇了... 最后在这里讨论LCT的一个常用操作:维护虚子树信息 这也是一个常用操作 下面我们看一下如何来维护 以下内容转自https://blog.csdn.net/neither_ ...

  4. SPLAY,LCT学习笔记(五)

    这一篇重点探讨LCT的应用 例:bzoj 2631 tree2(国家集训队) LCT模板操作之一,利用SPLAY可以进行区间操作这一性质对维护懒惰标记,注意标记下传顺序和如何下传 #include & ...

  5. SPLAY,LCT学习笔记(四)

    前三篇好像变成了SPLAY专题... 这一篇正式开始LCT! 其实LCT就是基于SPLAY的伸展操作维护树(森林)连通性的一个数据结构 核心操作有很多,我们以一道题为例: 例:bzoj 2049 洞穴 ...

  6. SPLAY,LCT学习笔记(一)

    写了两周数据结构,感觉要死掉了,赶紧总结一下,要不都没学明白. SPLAY专题: 例:NOI2005 维修数列 典型的SPLAY问题,而且综合了SPLAY常见的所有操作,特别适合新手入门学习(比如我这 ...

  7. SPLAY,LCT学习笔记(三)

    前两篇讲述了SPLAY模板操作,这一篇稍微介绍一下SPLAY的实际应用 (其实只有一道题,因为本蒟蒻就写了这一个) 例:bzoj 1014火星人prefix 由于本蒟蒻不会后缀数组,所以题目中给的提示 ...

  8. SPLAY,LCT学习笔记(二)

    能够看到,上一篇的代码中有一段叫做find我没有提到,感觉起来也没有什么用,那么他的存在意义是什么呢? 接下来我们来填一下这个坑 回到我们的主题:NOI 2005维修数列 我们刚刚讨论了区间翻转的操作 ...

  9. LCT学习笔记

    最近自学了一下LCT(Link-Cut-Tree),参考了Saramanda及Yang_Zhe等众多大神的论文博客,对LCT有了一个初步的认识,LCT是一种动态树,可以处理动态问题的算法.对于树分治中 ...

  10. [总结] LCT学习笔记

    \(emmm\)学\(lct\)有几天了,大概整理一下这东西的题单吧 (部分参考flashhu的博客) 基础操作 [洛谷P1501Tree II] 题意 给定一棵树,要求支持 链加,删边加边,链乘,询 ...

随机推荐

  1. yb课堂 首页home开发 《三十七》

    Home模块开发 拆分子组件 Home banner videoList 指令属性里面取data里面的数据不用加{{}},html标签内容体中间则需要加双花括号 创建component文件夹 在src ...

  2. Kafka消费端抛出异常Offset commit cannot be completed since the consumer is not part of an active group for auto partition assignment; it is likely that the consumer was kicked out of the group的解决方案

    总结/朱季谦 在一次测试Kafka通过consumer.subscribe()指定偏移量Offset消费过程中,因为设置参数不当,出现了一个异常提示-- [2024-01-04 16:06:32.55 ...

  3. CF-957(D-E)

    CF-957 赛时A去写全排列--前三题我的写法都挺丑的,后面改进了再更-- Problem - D - Codeforces 虽然是很简单很经典的线性dp,但也是我第一次自己把这种题写出来ヾ(≧▽≦ ...

  4. 将虚拟机跑在ceph之中

    目录 openStack对接ceph 1. cinder对接ceph 1.1 ceph创建存储池 1.2 ceph授权 1.3 下发ceph文件 1.4 修改globals文件 1.5 部署cinde ...

  5. 【进阶篇】一文搞清楚网页发起 HTTP 请求调用的完整过程

    目录 前言 一.HTTP协议 1.1基本概念 1.2工作原理 二.请求过程 2.1域名解析 2.2TCP 连接 2.3发送 HTTP 请求 2.4服务器应答 2.5响应内容 2.6关闭连接 三.客户端 ...

  6. 在Visual Studio Code中,鼠标双击PHP变量的时候,如何选择包括$在内的整个变量名

    依次点击:文件->首选项->设置 并在"editor.wordSeparators"设置中为您的语言指定删除"$"符号:

  7. vue小知识:多层数据双向相应之向上派发和向下派发($dispatch和$broadcast)

    注意:这两个实例已经在vue3中弃用啦!!!(所以不详细说了,封装知道怎么用就行了,作为了解) 都是在vue实例配置(main.js) 向上派发:$dispatch 注意,在相应后代组件中使用 thi ...

  8. Python 华为云OSS建桶与文件上传下载删除及检索示例

    华为云OSS建桶与文件上传下载删除及检索示例 实践环境 运行环境: Python 3.5.4 CentOS Linux release 7.4.1708 (Core)/Win10 需要安装以下类库: ...

  9. 【Java】【常用类】SimpleDateFormat 简单日期格式化类

    Date类的API不易于国际化,大部分基本摈弃了 java.text.SimpleDateFormate 不和语言环境有关的方式来格式化和解析日期的具体类 支持 文本转格式,格式转文本 public ...

  10. 【Hibernate】Re03 注解方式实现

    使用JPA规范提供的注解即可实现,这样的好处是不需要配置Entity.hbm.xml文件了 但是考虑到多表查询的情况,还是会有xml配置的需要. 一.常用的JPA注解: 1.public @inter ...