开个坑记录一下学习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. MS SQLServer相关自动化程序的问题汇总 (SQLServer每天定时输出EXCEL或xml的格式的问题等 )

    · MS SQLServer相关问题 1. 使用MS SQLServer每天定时输出EXCEL格式的文件,实现每天的Excel报表导出 2. 使用MS SQLServer每天定时输出xml格式的文件, ...

  2. H5_0009:关于HTML5中Canvas的宽、高设置问题

    关于HTML5中Canvas的宽.高设置问题 Canvas元素默认宽 300px, 高 150px, 设置其宽高可以使用如下方法(不会被拉伸): 方法一:        <canvas widt ...

  3. dev 控件用法2 之repositoryItemSearchLookUpEdit

    repositoryItemSearchLookUpEdit var y = userinfo.Select.ToList( a => new { userid = a.userid, code ...

  4. Visual Studio Code搭建Python开发环境方法总结

    更新:目前VSCode官方Python插件已经支持代码运行与调试,无需安装Code Runner插件. 1.下载安装Python,地址 https://www.python.org/downloads ...

  5. 洛谷P1200 [USACO1.1]你的飞碟在这儿Your Ride Is Here

    题目描述 众所周知,在每一个彗星后都有一只UFO.这些UFO时常来收集地球上的忠诚支持者.不幸的是,他们的飞碟每次出行都只能带上一组支持者.因此,他们要用一种聪明的方案让这些小组提前知道谁会被彗星带走 ...

  6. vue加载单文件使用vue-loader报错

    报错信息如下:ERROR in ./src/login.vue Module Error (from ./node_modules/vue-loader/lib/index.js): vue-load ...

  7. 【Python】1.PyQT5界面初尝试

    1->通过pycharm打开QTdesigner.创建新Form. 2->选择Widget创建 3->不添加任何控件 点击保存 pycharm列表如下 后缀名位ui的  即QTdes ...

  8. Django 初试水(三)

    在前面的一和二中,分别实现了一些基础的操作,数据库和 Django 自带的管理界面,接下来,主要是创建我们自己的界面(视图). 访问一个地址,对应的服务器直接返回一个视图.这是最常见的交互. 就好比访 ...

  9. linux命令解压压缩rar文件的详细步骤

    参考文件:https://www.cnblogs.com/qinglin/p/9007939.html

  10. phpstorm实现分屏展示代码

    第一种 选择你要分屏的页面 [Window]—>[Editor Tabs]—>[Split Vertically]or[Split Horizontally]  第二种 把鼠标箭头放到你想 ...