开个坑记录一下学习Splay的历程。

Code

感谢rqy巨佬的代码,让我意识到了Splay可以有多短,以及我之前的Splay有多么的丑...

int fa[N], ch[N][2], rev[N], sz[N], n;

void upd(int x) { sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + 1; }
void pd(int x) {
if (rev[x]) {
std::swap(ch[x][0], ch[x][1]);
rev[ch[x][0]] ^= 1;
rev[ch[x][1]] ^= 1;
rev[x] = 0;
}
}
int dir(int x) { return x == ch[fa[x]][1]; }
void rot(int x) {
int f = fa[x], d = dir(x);
if (fa[x] = fa[f]) ch[fa[x]][dir(f)] = x;
if (ch[f][d] = ch[x][d^1]) fa[ch[f][d]] = f;
fa[ch[x][d^1] = f] = x;
upd(f); upd(x);
}
int st[N];
void splay(int x, int t = 0) {
int top = 0;
for (int i = x; fa[i]; i = fa[i]) st[top++] = fa[i];
while (top--) pd(st[top]);
pd(x);
for (; fa[x] != t; rot(x)) if (fa[fa[x]] != t) rot(dir(fa[x]) == dir(x) ? fa[x] : x);
}
int kth(int k, int t) {
int o = t;
while (1) {
pd(o);
if (sz[ch[o][0]] == k-1) break;
else if (sz[ch[o][0]] >= k) o = ch[o][0];
else { k -= sz[ch[o][0]]+1; o = ch[o][1]; }
}
splay(o, fa[t]);
return o;
}
void reverse(int l, int r) {
splay(1);
int y = kth(r+1, 1);
int x = ch[y][0];
kth(l-1, x);
rev[ch[ch[y][0]][1]] ^= 1;
}

(以上是维护序列翻转的splay,码量1k多点,唯一的缺陷是压行太严重,不是很好调)

Note

一些小地方

这个Splay的根是fa[i]=0的点,但是怎么找呢?不用管,直接splay(1),这样1就是根了啊(好暴力啊)。

建树怎么建啊?也不用动脑子啊,直接建成一条链就行了啊,反正之后还要再调整,一开始建的那么完美没有用啊。

关于标记

一般维护序列问题,需要支持几种区间修改操作就打几个标记。

不要忘了在splay前先pushdown所有祖先节点。

区间翻转

这个还是比较简单的,直接记录就行。

区间加

这个维护起来也不是很难,就是要注意标记下放的时候对维护的值的处理。

关于应该维护的值

这一部分也是十分的坑啊,只能多做题找感觉了。

区间最值

要注意0号点的值,不要傻乎乎的取最值的时候让0号点影响到答案。

要分开维护每个节点的值和其子树的最值,不要偷懒只存一个啊(我有一个下午都浪费在了这上面...)。

[Note]Splay学习笔记的更多相关文章

  1. 平衡树splay学习笔记#2

    讲一下另外的所有操作(指的是普通平衡树中的其他操作) 前一篇的学习笔记连接:[传送门],结尾会带上完整的代码. 操作1,pushup操作 之前学习过线段树,都知道子节点的信息需要更新到父亲节点上. 因 ...

  2. 平衡树splay学习笔记#1

    这一篇博客只讲splay的前一部分的操作(rotate和splay),后面的一段博客咕咕一段时间 后一半的博客地址:[传送门] 前言骚话 为了学lct我也是拼了,看了十几篇博客,学了将近有一周,才A掉 ...

  3. 文艺平衡树 Splay 学习笔记(1)

    (这里是Splay基础操作,reserve什么的会在下一篇里面讲) 好久之前就说要学Splay了,结果苟到现在才学习. 可能是最近良心发现自己实在太弱了,听数学又听不懂只好多学点不要脑子的数据结构. ...

  4. [Splay][学习笔记]

    胡扯 因为先学习的treap,而splay与treap中有许多共性,所以会有很多地方不会讲的很细致.关于treap和平衡树可以参考这篇博客 关于splay splay,又叫伸展树,是一种二叉排序树,它 ...

  5. splay学习笔记

    伸展树(Splay Tree),也叫分裂树,是一种二叉排序树,它能在O(log n)内完成插入.查找和删除操作.(来自百科) 伸展树的操作主要是 –rotate(x) 将x旋转到x的父亲的位置 voi ...

  6. 【洛谷P3391】文艺平衡树——Splay学习笔记(二)

    题目链接 Splay基础操作 \(Splay\)上的区间翻转 首先,这里的\(Splay\)维护的是一个序列的顺序,每个结点即为序列中的一个数,序列的顺序即为\(Splay\)的中序遍历 那么如何实现 ...

  7. 【洛谷P3369】普通平衡树——Splay学习笔记(一)

    二叉搜索树(二叉排序树) 概念:一棵树,若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值: 它的左.右子树也分别为二叉搜索树 ...

  8. [学习笔记]平衡树(Splay)——旋转的灵魂舞蹈家

    1.简介 首先要知道什么是二叉查找树. 这是一棵二叉树,每个节点最多有一个左儿子,一个右儿子. 它能支持查找功能. 具体来说,每个儿子有一个权值,保证一个节点的左儿子权值小于这个节点,右儿子权值大于这 ...

  9. 平衡树学习笔记(3)-------Splay

    Splay 上一篇:平衡树学习笔记(2)-------Treap Splay是一个实用而且灵活性很强的平衡树 效率上也比较客观,但是一定要一次性写对 debug可能不是那么容易 Splay作为平衡树, ...

随机推荐

  1. 集合使用 Iterator 删除元素

    针对常见的数据集合,比如 ArrayList 列表,对其进行遍历,删除其中符合条件的某个元素,使用 iterator 迭代器进行迭代,代码如下: public class PracticeContro ...

  2. Android studio中为项目添加模块依赖的过程

    https://blog.csdn.net/cheng__lu/article/details/74574582 Android studio中为项目添加模块依赖的过程 1.点击菜单file>p ...

  3. 真·从零开始的Ubuntu+Apache+MySQL+PHP+phpstorm+xdebug下的debug环境搭建(纯小白向)

    费了好几天劲,终于把Linux下的开发环境如何设置搞的有点明白了,在此写篇博客庆祝一下,让大家以后少踩坑(缓慢更新中) 关键词 win10双系统装Ubuntu 下载U盘烧录工具 下载UbuntuLTS ...

  4. kali的virtualbox镜像账号密码

    下载最新版本kali的virtualbox镜像 默认账号密码 root  密码 toor

  5. java 8 supplier object区别

    起初用supplier的时候,发现用法和object一样呀,只是一个用于生产object工厂方法而已,为什么要新引起这样一个对象呢. 后面查到这篇英语文档,才发现,相比object有如下三个用法: ( ...

  6. pytest+requests+Python3.7+yaml+Allure+Jenkins+docker实现接口自动化测试

    接口自动化测试框架(用例自动生成) 项目说明 本框架是一套基于pytest+requests+Python3.7+yaml+Allure+Jenkins+docker而设计的数据驱动接口自动化测试框架 ...

  7. java - CAS及CAS底层原理

    CAS是什么? CAS的全称为Compare-And-Swap它是一条CPU并发原语,也就是在CPU硬件层面上来说比较并且判断是否设置新值这段操作是原子性的,不会被其他线程所打断.在JAVA并发包ja ...

  8. linux基础安全

    一.用户防护 Chage  -l  用户名   查看用户账号有效期信息 Chage  -E   时间   用户名   给用户设置过期时间 /etc/login.defs  文件保存许多默认设置 Pas ...

  9. tomcat常见状态码

  10. 设置Eclipse中的字符集为UTF-8

    Eclipse 修改字符集 默认情况下 Eclipse 字符集为 GBK,但现在很多项目采用的是 UTF-8,这是我们就需要设置我们的 Eclipse 开发环境字符集为 UTF-8, 设置步骤如下: ...