SPLAY or SPALY ?
写在前面:
由我们可爱的Daniel Sleator和Robert Tarjan提出的一种数据结构,平衡树的一种,本质是二叉树。
至于到底是splay还是spaly,我认为可能splay更对一些
毕竟splay是有实意的单词,更有可能一点。而且WIKI百科页也是splay
以下是本人学习splay的一点过程,请多指教喽
SPLAY
那么我在这里复习整理一下spaly的代码相关吧
例题:http://www.lydsy.com/JudgeOnline/problem.php?id=3224
参考博客:http://blog.csdn.net/clove_unique/article/details/50636361
#include<cstdio>
#define maxn 500100
using namespace std;
int root,N,tot;
inline int read(){
register int x=,t=;
register char ch=getchar();
while((ch<''||ch>'')&&ch!='-')ch=getchar();
if(ch=='-'){t=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-;ch=getchar();}
return x*t;
}
struct node{
int ch[],ff,cnt,val,sum;
}t[maxn];
void pushup(int u){
t[u].sum=t[t[u].ch[]].sum+t[t[u].ch[]].sum+t[u].cnt;
}
void rotate(int x){
register int y=t[x].ff;
register int z=t[y].ff;
register int k=t[y].ch[]==x;
t[z].ch[t[z].ch[]==y]=x;t[x].ff=z;
t[y].ch[k]=t[x].ch[k^];t[t[x].ch[k^]].ff=y;
t[x].ch[k^]=y;t[y].ff=x;
pushup(y),pushup(x);
}
void splay(int x,int goal){
while(t[x].ff!=goal){
int y=t[x].ff;
int z=t[y].ff;
if(z!=goal)
(t[y].ch[]==x)^(t[z].ch[]==y)?rotate(x):rotate(y);
rotate(x);
}
if(goal==)
root=x;
}
void insert(int x){
int u=root,ff=;
while(u&&t[u].val!=x){
ff=u;
u=t[u].ch[x>t[u].val];
}
if(u)
t[u].cnt++;
else{
u=++tot;
if(ff)
t[ff].ch[x>t[ff].val]=u;
t[tot].ch[]=;
t[tot].ch[]=;
t[tot].ff=ff;t[tot].val=x;
t[tot].cnt=t[tot].sum=;
}
splay(u,);
}
void find(int x){
int u=root;
if(!u)return;
while(t[u].ch[x>t[u].val]&&x!=t[u].val)
u=t[u].ch[x>t[u].val];
splay(u,);
}
int next(int x,int f){
find(x);
int u=root;
if((t[u].val>x&&f)||(t[u].val<x&&!f))return u;
u=t[u].ch[f];
while(t[u].ch[f^])u=t[u].ch[f^];
return u;
}
void del(int x){
int la=next(x,);
int ne=next(x,);
splay(la,),splay(ne,la);
int d=t[ne].ch[];
if(t[d].cnt>){
t[d].cnt--;
splay(d,);
}
else
t[ne].ch[]=;
}
int K_th(int x){
int u=root;
if(t[u].sum<x)
return ;
while(){
int y=t[u].ch[];
if(x>t[y].sum+t[u].cnt){
x-=t[y].sum+t[u].cnt;
u=t[u].ch[];
}
else if(t[y].sum>=x)
u=y;
else
return t[u].val;
}
}
int main(){
insert(-);
insert(+);
N=read();
while(N--){
int opt=read();
if(opt==)insert(read());
else if(opt==)del(read());
else if(opt==){
find(read());
printf("%d\n",t[t[root].ch[]].sum);
}
else if(opt==)printf("%d\n",K_th(read()+));
else if(opt==)printf("%d\n",t[next(read(),)].val);
else if(opt==)printf("%d\n",t[next(read(),)].val);
}
return ;
}
上面那份代码其实是洛谷上的。。。本来想自己写的,但是怎么调都过不去5555(;´д`)ゞ
算了吧,既然抄了代码就要抄的明明白白,这里让我们看看splay到底是怎么维护的吧
首先是一些基本操作:
1.rotate

就是这个东西,保证了二叉树储存的元素顺序不变,大小顺序不变,总之转它就对了。
void rotate(int x){
register int y=t[x].ff;
register int z=t[y].ff;
register int k=t[y].ch[]==x;
t[z].ch[t[z].ch[]==y]=x;t[x].ff=z;
t[y].ch[k]=t[x].ch[k^];t[t[x].ch[k^]].ff=y;
t[x].ch[k^]=y;t[y].ff=x;
pushup(y),pushup(x);
}
2.splay
splay是依靠平均操作来降低复杂度的,其实有点玄学,splay这个操作就是要把每次查询和修改的中心重新改变成根,
在这个过程中尽可能的让树的大小平衡,即尽可能打断原先树上存在的链,把他们压成树。。。
反正挺神的,记住写双旋时有先后就对了,尽量让树平衡。
void splay(int x,int goal){
while(t[x].ff!=goal){
int y=t[x].ff;
int z=t[y].ff;
if(z!=goal)
(t[y].ch[]==x)^(t[z].ch[]==y)?rotate(x):rotate(y);
rotate(x);
}
if(goal==)
root=x;
}
em。。。接下来挑一些重点(我蒙过的)讲吧。。。
3.del
删除操作,为了精确定位我们想删掉的那个点,我们选择找到他的前驱,旋到根上,再找他的后继,旋到前驱下面
这样的话这个点只能在后继的左儿子上了
但是如果这个点没有前驱和后继岂不是药丸
SPLAY or SPALY ?的更多相关文章
- [BZOJ4825][HNOI2017]单旋spaly
BZOJ Luogu 题目太长了,就不放了. 题解 首先声明一点,无论是splay还是spaly,插入一个新的元素,都要rotate到根!所以说题目也算是给了一个错误示范吧. 我们发现把最值旋转到根并 ...
- [BZOJ4825][HNOI2017]单旋(线段树+Splay)
4825: [Hnoi2017]单旋 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 667 Solved: 342[Submit][Status][ ...
- bzoj4825 [Hnoi2017]单旋
Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...
- BZOJ:4825: [Hnoi2017]单旋
Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...
- HNOI2017 单旋
题目描述 网址:https://www.luogu.org/problemnew/show/3721 大意: 有一颗单旋Splay(Spaly),以key值为优先度,总共有5个操作. [1] 插入一个 ...
- [HNOI 2017]单旋
Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据 结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的 ...
- bzoj P4825 [Hnoi2017]单旋——solution
Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据 结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的 ...
- 【刷题】BZOJ 4825 [Hnoi2017]单旋
Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必 ...
- bzo j4825 [Hnoi2017]单旋
Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据 结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的 ...
随机推荐
- [bzoj1455]罗马游戏_左偏树_并查集
罗马游戏 bzoj-1455 题目大意:给你n个人,2种操作,m次操作:1.将i号士兵所在的集合的最小值删除 2.合并i和j两个士兵所在的团体 注释:$1\le n\le 10^6$,$1\le m ...
- Java 和JS Base64加密
项目在登录.注册等场景实现时,经常会用到用户信息前端加密,然后项目后端二次解密,避免信息直接在浏览器上以明文显示. 本文主要介绍了base64加密的方式处理代码,不支持中文 源码如下: base64. ...
- JAVA 大数据
- IntelliJ IDEA 14注冊码
User:xring Key:21423-V4P36-U7W8K-8CYUK-93HXA-MKGZ5 User:arix Key:52998-LJT74-J7YEX-UPVT3-Q5GUF-5G4B5 ...
- 转:分布式事务之TCC服务设计和实现注意事项
由公司微服务培训引起的一丢丢对TCC的好奇 原文:https://yq.aliyun.com/articles/609854 一.TCC简介 TCC是一种比较成熟的分布式事务解决方案,可用于解决跨库操 ...
- Mysql查看sql是否走事务
登陆进入server [root@gzmtest_25 ~]# su - mysql [mysql@gzmtest_25 ~]$ mysql.local Welcome to the MySQL mo ...
- 关注C-RAN 的五大理由
关注C-RAN的五大理由 Scott Wakelin 近期行业媒体上有大量关于移动网络运营商(如美国的VerizonWireless和AT&T.法国电信以及中国移动等)怎样在着力探索一种 ...
- luogu1005 矩阵取数游戏
题目大意 一个矩阵,每次从每一行的行首或行尾取一个数,每一行的价值为 取的数*2^当前取数的次数,每一次的价值为每一行的价值的和.求得到的价值的最大值. 思路 #include <cstdio& ...
- Linux framebuffer显示bmp图片【转】
本文转载自:http://blog.csdn.net/luxiaoxun/article/details/7622988 framebuffer简介 帧缓冲(framebuffer)是Linux为显示 ...
- Android内存解析(一)—从Linux系统内存逐步认识Android应用内存
总述 Android应用程序被限制了内存使用上限,一般为16M或24M(具体看系统设置),当应用的使用内存超过这个上限时,就会被系统认为内存泄漏,被kill掉.所以在android开发时,管理好内存的 ...