平衡树——splay 一
splay
一种平衡树,同时也是二叉排序树,与treap不同,它不需要维护堆的性质,它由Daniel Sleator和Robert Tarjan(没错,tarjan,又是他)创造,伸展树是一种自调整二叉树,它会将一个节点沿着到根的路径旋转上去。
空间效率:On
摊平时间效率:Ologn
建议先学会treap
treap(小根堆)模板 - yi_fan0305 - 博客园 (cnblogs.com)
treap(大根堆)模板 - yi_fan0305 - 博客园 (cnblogs.com)
存储结构
int ch[N][2],fa[N];//左孩子,右孩子,父亲
ll val[N],siz[N],cnt[N];//点值
数组存储,也可以用结构体。
基本操作:
一、旋转
与treap的旋转无太大差异,只要注意更新父节点就行了,记得要更新siz。
splay的旋转函数的参数,是转上去的那个数值,这里与treap不同,treap是转下来的数值。
这里旋转一定要注意次序,明白先处理哪个,再处理哪个,否则会RE!
一定要先处理x与y的孩子,再处理x与y。
void pushup(int id)//更新siz
{
siz[id]=siz[ch[id][0]]+siz[ch[id][1]]+cnt[id];
}
void spin(int x)
{
rint y=fa[x],z=fa[y],d=(ch[y][1]==x);//d 判断x是y的左孩子还是右孩子
ch[z][ch[z][1]==y]=x,fa[x]=z;//处理x与z的关系
ch[y][d]=ch[x][d^1],fa[ch[x][d^1]]=y;//处理y的孩子与x的孩子的关系
ch[x][d^1]=y;fa[y]=x;//处理y与x的关系
pushup(y);//先更新y
pushup(x);//在更新x
}
二、伸展
情况一:
x要移动到父节点的位置
自己懒得画了,用的教练课件上的图
直接旋转x即可
情况二:
情况二:X点要移到到g或更向上的位置且g->p和p->x是同一方向。
这里要先旋转p,再旋转x
情况三:
情况三:X点要移到到g或更向上的位置且g->p和p->x不是是同一方向。
这里旋转两次x
你会发现,最后一次都是旋转x
void splay(int x,int goal)
{
while(fa[x]!=goal)//判断是否已经到目标点的下边
{
rint y=fa[x],z=fa[y];
if(z!=goal)//判断是情况一还是情况二、三
(ch[y][0]==x)^(ch[z][0]==y)?spin(x):spin(y);
//判断是情况二还是情况三
spin(x);
}
if(goal==0) root=x;//如果移动到了根节点,则更新根节点
}
三、插入节点
只要记得处理父节点就行了。
void insert(ll x)
{
int u=root,fat=0;
while(u&&val[u]!=x)//先向下找
{
fat=u;
u=ch[u][x>val[u]];
}
if(u) cnt[u]++;
else
{
u=++tot;
if(fat) ch[fat][x>val[fat]]=u;//如果不是根节点,更新孩子节点
fa[u]=fat;//插入操作
val[u]=x;
siz[u]=1;
cnt[u]=1;
}
splay(u,0);//每次都要伸展,避免成链
}
四、查找结点
按照二叉排序树找到节点,然后将该节点伸展到到根节点就行了。
void find(ll x)
{
int u=root;
if(!u) return;//不存在该节点,直接返回
while(ch[u][x>val[u]]&&x!=val[u])//找到该节点的位置
u=ch[u][x>val[u]];
splay(u,0);//伸展
}
五、查找前驱后继
先将要查找的值的位置或相邻的位置伸展到根节点,然后在左右子树中搜索。
int get(ll x,int d)//d:0找前驱 1找后继
{
find(x);//先伸展
int u=root;
if((val[u]>x&&d)||(val[u]<x&&!d)) return u;
//如果该节点已经符合要求,直接返回位置
u=ch[u][d];//找到左右子树
while(ch[u][d^1]) u=ch[u][d^1];
//找左子树中最大的或右子树中最小的(关键看你找前驱还是后继)
return u;//返回前驱或后继的位置
}
六、删除节点
先找到前驱和后继,将前驱伸展到根节点,将后继伸展到前驱下面,根据二叉查找树的性质,后继的左孩子就是我们要删的点,进行操作即可。
void del(ll x)
{
int pre=get(x,0),nxt=get(x,1);//找前驱后继
splay(pre,0),splay(nxt,pre);//伸展
int id=ch[nxt][0];//要删除的点
if(cnt[id]>1)//如果这个数值有重复,直接--cnt即可
{
--cnt[id];
splay(id,0);//伸展
}
else
{
ch[nxt][0]=0,fa[id]=0;//先切断联系
val[id]=0,cnt[id]=0,siz[id]=0;//再进行删除
pushup(nxt),pushup(pre);//最后更新siz
}
}
最基础的就只有这些了,其他操作以后更新。
来自未来的链接:
平衡树——splay 二 - yi_fan0305 - 博客园 (cnblogs.com)
平衡树——splay 三 - yi_fan0305 - 博客园 (cnblogs.com)
平衡树——splay 一的更多相关文章
- hiho #1329 : 平衡树·Splay
#1329 : 平衡树·Splay 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho:小Hi,上一次你跟我讲了Treap,我也实现了.但是我遇到了一个关键的问题. ...
- 【BZOJ3224】Tyvj 1728 普通平衡树 Splay
Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数 ...
- BZOJ3224/洛谷P3391 - 普通平衡树(Splay)
BZOJ链接 洛谷链接 题意简述 模板题啦~ 代码 //普通平衡树(Splay) #include <cstdio> int const N=1e5+10; int rt,ndCnt; i ...
- Hihocoder 1329 平衡树·Splay(平衡树)
Hihocoder 1329 平衡树·Splay(平衡树) Description 小Ho:小Hi,上一次你跟我讲了Treap,我也实现了.但是我遇到了一个关键的问题. 小Hi:怎么了? 小Ho:小H ...
- 【阶梯报告】洛谷P3391【模板】文艺平衡树 splay
[阶梯报告]洛谷P3391[模板]文艺平衡树 splay 题目链接在这里[链接](https://www.luogu.org/problemnew/show/P3391)最近在学习splay,终于做对 ...
- luoguP3391[模板]文艺平衡树(Splay) 题解
链接一下题目:luoguP3391[模板]文艺平衡树(Splay) 平衡树解析 这里的Splay维护的显然不再是权值排序 现在按照的是序列中的编号排序(不过在这道题目里面就是权值诶...) 那么,继续 ...
- 平衡树——splay 三
前文链接: 平衡树--splay 一 - yi_fan0305 - 博客园 (cnblogs.com) 平衡树--splay 二 - yi_fan0305 - 博客园 (cnblogs.com) 再补 ...
- 平衡树——splay 二
上文传送门:平衡树--splay 一 - yi_fan0305 - 博客园 (cnblogs.com) OK,我们继续上文,来讲一些其他操作. 七.找排名为k的数 和treap的操作很像,都是通过比较 ...
- BZOJ3223: Tyvj 1729 文艺平衡树 [splay]
3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3595 Solved: 2029[Submit][Sta ...
随机推荐
- Docker系列教程05-Docker数据卷(Data Volume)学习
引言 在Docker中,容器的数据读写默认发生在容器的存储层,当容器被删除时其上的数据将会丢失.要想实现数据的持久化,需要将数据从宿主机挂载到容器中.目前Docker提供了三种方式将数据从宿主机挂载到 ...
- C++进阶-1-模板基础(函数模板、类模板)
C++进阶 模板 1.1 函数模板 1 #include<iostream> 2 using namespace std; 3 4 // 模板 5 6 // 模板的简单实例 7 // 要求 ...
- 【Java分享客栈】超简洁SpringBoot使用AOP统一日志管理-纯干货干到便秘
前言 请问今天您便秘了吗?程序员坐久了真的会便秘哦,如果偶然点进了这篇小干货,就麻烦您喝杯水然后去趟厕所一边用左手托起对准嘘嘘,一边用右手滑动手机看完本篇吧. 实现 本篇AOP统一日志管理写法来源于国 ...
- IIS项目部署和发布
VS2019如何把项目部署和发布 这里演示:通过IIS文件publish的方式部署到Windows本地服务器上 第一步(安装IIS) 1.在自己电脑上搜索Windows功能里的[启用或关闭Window ...
- Svelte3.x网页聊天实例|svelte.js仿微信PC版聊天svelte-webchat
基于Svelte3+SvelteKit+Sass仿微信Mac界面聊天实战项目SvelteWebChat. 基于svelte3+svelteKit+sass+mescroll.js+svelte-lay ...
- vs code 终端字体间距过大(全角的样子)
文件-首选项-设置 将 terminal.integrated.fontFamily 配置为 Consolas, 'Courier New', monospace 或其他想要的字体,或者点击齿轮按钮重 ...
- 好客租房21-react组件的两种创建方式(函数组件)
1使用函数创建组件 函数组件:使用js的函数或者箭头函数创建的组件 约定1:函数组件名称必须以 开头 约定2:函数组件必须有返回值 表示该组件的结构 如果返回值为null 表示不渲染任何内容 2.1使 ...
- 140_Power BI&Power Pivot之降维展示同类型比较
博客:www.jiaopengzi.com 焦棚子的文章目录 请点击下载附件 一.背景 最近一段时间比较忙,几乎没有时间更新网站内容,今天刚好周末,更新一个简单的需求. 上效果图: 在我们日常做对比分 ...
- vs 快速定位文件
在进行web开发时,我们经常需要在文件之间进行切换,每次在VS的解决方案中找文件然后打开 非常浪费时间,有没有比较快捷点的方法呢? 1.使用 ReSharper 插件 ReSharper 插件可以在 ...
- Java - 六原则一法则
Java - 六原则一法则 单一职责原则:一个类只做它该做的事情.(单一职责原则想表达的就是"高内聚",写代码最终极的原则只有六个字"高内聚.低耦合",所谓的高 ...