Splay/LCT 学习笔记
唔,其实我不会 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\) 与 原树上的根 之间的路径取出。
注意点:
操作完后 \(x\) 有实儿子,但是只会有左儿子,即原树的到根的链上的节点,所以得到的是一条从 根 到 \(x\) 的链,没有其他节点。
pushup(x)
Splay/LCT 学习笔记的更多相关文章
- LCT 学习笔记
LCT学习笔记 前言 自己定的学习计划看起来完不成了(两天没学东西,全在补题),决定赶快学点东西 于是就学LCT了 简介 Link/Cut Tree是一种数据结构,我们用它解决动态树问题 但是LCT不 ...
- BST,Splay平衡树学习笔记
BST,Splay平衡树学习笔记 1.二叉查找树BST BST是一种二叉树形结构,其特点就在于:每一个非叶子结点的值都大于他的左子树中的任意一个值,并都小于他的右子树中的任意一个值. 2.BST的用处 ...
- SPLAY,LCT学习笔记(六)
这应该暂时是个终结篇了... 最后在这里讨论LCT的一个常用操作:维护虚子树信息 这也是一个常用操作 下面我们看一下如何来维护 以下内容转自https://blog.csdn.net/neither_ ...
- SPLAY,LCT学习笔记(五)
这一篇重点探讨LCT的应用 例:bzoj 2631 tree2(国家集训队) LCT模板操作之一,利用SPLAY可以进行区间操作这一性质对维护懒惰标记,注意标记下传顺序和如何下传 #include & ...
- SPLAY,LCT学习笔记(四)
前三篇好像变成了SPLAY专题... 这一篇正式开始LCT! 其实LCT就是基于SPLAY的伸展操作维护树(森林)连通性的一个数据结构 核心操作有很多,我们以一道题为例: 例:bzoj 2049 洞穴 ...
- SPLAY,LCT学习笔记(一)
写了两周数据结构,感觉要死掉了,赶紧总结一下,要不都没学明白. SPLAY专题: 例:NOI2005 维修数列 典型的SPLAY问题,而且综合了SPLAY常见的所有操作,特别适合新手入门学习(比如我这 ...
- SPLAY,LCT学习笔记(三)
前两篇讲述了SPLAY模板操作,这一篇稍微介绍一下SPLAY的实际应用 (其实只有一道题,因为本蒟蒻就写了这一个) 例:bzoj 1014火星人prefix 由于本蒟蒻不会后缀数组,所以题目中给的提示 ...
- SPLAY,LCT学习笔记(二)
能够看到,上一篇的代码中有一段叫做find我没有提到,感觉起来也没有什么用,那么他的存在意义是什么呢? 接下来我们来填一下这个坑 回到我们的主题:NOI 2005维修数列 我们刚刚讨论了区间翻转的操作 ...
- LCT学习笔记
最近自学了一下LCT(Link-Cut-Tree),参考了Saramanda及Yang_Zhe等众多大神的论文博客,对LCT有了一个初步的认识,LCT是一种动态树,可以处理动态问题的算法.对于树分治中 ...
- [总结] LCT学习笔记
\(emmm\)学\(lct\)有几天了,大概整理一下这东西的题单吧 (部分参考flashhu的博客) 基础操作 [洛谷P1501Tree II] 题意 给定一棵树,要求支持 链加,删边加边,链乘,询 ...
随机推荐
- yb课堂 首页home开发 《三十七》
Home模块开发 拆分子组件 Home banner videoList 指令属性里面取data里面的数据不用加{{}},html标签内容体中间则需要加双花括号 创建component文件夹 在src ...
- 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 ...
- CF-957(D-E)
CF-957 赛时A去写全排列--前三题我的写法都挺丑的,后面改进了再更-- Problem - D - Codeforces 虽然是很简单很经典的线性dp,但也是我第一次自己把这种题写出来ヾ(≧▽≦ ...
- 将虚拟机跑在ceph之中
目录 openStack对接ceph 1. cinder对接ceph 1.1 ceph创建存储池 1.2 ceph授权 1.3 下发ceph文件 1.4 修改globals文件 1.5 部署cinde ...
- 【进阶篇】一文搞清楚网页发起 HTTP 请求调用的完整过程
目录 前言 一.HTTP协议 1.1基本概念 1.2工作原理 二.请求过程 2.1域名解析 2.2TCP 连接 2.3发送 HTTP 请求 2.4服务器应答 2.5响应内容 2.6关闭连接 三.客户端 ...
- 在Visual Studio Code中,鼠标双击PHP变量的时候,如何选择包括$在内的整个变量名
依次点击:文件->首选项->设置 并在"editor.wordSeparators"设置中为您的语言指定删除"$"符号:
- vue小知识:多层数据双向相应之向上派发和向下派发($dispatch和$broadcast)
注意:这两个实例已经在vue3中弃用啦!!!(所以不详细说了,封装知道怎么用就行了,作为了解) 都是在vue实例配置(main.js) 向上派发:$dispatch 注意,在相应后代组件中使用 thi ...
- Python 华为云OSS建桶与文件上传下载删除及检索示例
华为云OSS建桶与文件上传下载删除及检索示例 实践环境 运行环境: Python 3.5.4 CentOS Linux release 7.4.1708 (Core)/Win10 需要安装以下类库: ...
- 【Java】【常用类】SimpleDateFormat 简单日期格式化类
Date类的API不易于国际化,大部分基本摈弃了 java.text.SimpleDateFormate 不和语言环境有关的方式来格式化和解析日期的具体类 支持 文本转格式,格式转文本 public ...
- 【Hibernate】Re03 注解方式实现
使用JPA规范提供的注解即可实现,这样的好处是不需要配置Entity.hbm.xml文件了 但是考虑到多表查询的情况,还是会有xml配置的需要. 一.常用的JPA注解: 1.public @inter ...