Splay初学习
听YZ哥哥说Splay是一种很神奇的数据结构,所以学习了一下它的最基本操作。O(1)的Spaly。
伸展树(Splay Tree),也叫分裂树,是一种二叉排序树,它能在O(logn)内完成插入、查找和删除操作。它由丹尼尔·斯立特Daniel Sleator和罗伯特·恩卓·塔扬Robert Endre Tarjan在1985年发明的。在伸展树上的一般操作都基于伸展操作:假设想要对一个二叉查找树执行一系列的查找操作,为了使整个查找时间更小,被查频率高的那些条目就应当经常处于靠近树根的位置。于是想到设计一个简单方法, 在每次查找之后对树进行重构,把被查找的条目搬移到离树根近一些的地方。伸展树应运而生。伸展树是一种自调整形式的二叉查找树,它会沿着从某个节点到树根之间的路径,通过一系列的旋转把这个节点搬移到树根去。它的优势在于不需要记录用于平衡树的冗余信息。
#include <cstdio>
#include <cstring>
using namespace std; int read()
{
char c;while(c=getchar(),(c<''||c>'')&&c!='-');
int x=,y=;c=='-'?y=-:x=c-'';
while(c=getchar(),c>=''&&c<='')x=x*+c-'';
return x*y;
} int N,dist; struct Splay{
int tr[][],v[],tot[];
int f[],fa[],root,cnt;
Splay(){
memset(tr,,sizeof tr);
memset(v,,sizeof v);
memset(tot,,sizeof tot);
memset(f,,sizeof f);
cnt=root=;
}//初始化 void clear(int x){tr[x][]=tr[x][]=f[x]=fa[x]=tot[x]=v[x]=;}//清除节点信息
void up(int x){f[x]=f[tr[x][]]+f[tr[x][]]+tot[x];}//更新节点信息
int get(int x){return tr[fa[x]][]==x;}//which son of father void rotate(int &x)
{
int ol=fa[x],olol=fa[ol],to=get(x);
tr[ol][to]=tr[x][to^];fa[tr[x][to^]]=ol;
fa[ol]=x;tr[x][to^]=ol;
fa[x]=olol;
if(olol)//如果该节点的父亲的父亲存在
tr[olol][tr[olol][]==ol]=x;
up(ol);up(x);//这里一定要先更新ol,在更新x,想想为什么
} void splay(int x)
{
for(int S;S=fa[x];rotate(x))//先旋x
if(fa[S])//S不为根
rotate((get(x)==get(S)?S:x));//判断是否三点一线
root=x;
} void insert(int &x,int val,int pos)
{
if(!x){//插入
x=++cnt;
f[x]=tot[x]=,v[x]=val,fa[x]=pos;
dist=x;//记录节点
return ;
}
if(val==v[x]){dist=x,tot[x]++;return ;}//有一样的数
insert(tr[x][val>v[x]],val,x);
up(x);//更新
return ;
} int QueryX(int x,int val)//查询x的排名
{
if(!x)return ;
if(val==v[x])return f[tr[x][]]+;
int to=val>v[x];
return QueryX(tr[x][to],val)+(to?f[tr[x][]]+tot[x]:);
}
int QueryK(int x,int kth)//查询排名为K的数
{
if(!x)return ;
if(kth<=f[tr[x][]])return QueryK(tr[x][],kth);
if(kth>f[tr[x][]]+tot[x])return QueryK(tr[x][],kth-(f[tr[x][]]+tot[x]));
return v[x];
} void pre(int x,int val)//前驱
{
if(!x)return ;
if(val<=v[x])return pre(tr[x][],val);
else dist=x,pre(tr[x][],val);
}
void bac(int x,int val)//后继
{
if(!x)return ;
if(v[x]<=val)bac(tr[x][],val);
else dist=x,bac(tr[x][],val);
} int find(int x,int val)//在del之前先找节点,记录,并Splay
{
if(!x)return ;
if(v[x]==val){splay(x);return x;}//找到
int to=val>v[x];
return find(tr[x][to],val);
}
void del(int x)//删除
{
int kkk=find(root,x);
if(!kkk)return ;//不存在
if(tot[root]>){
tot[root]--,up(root);
return ;
}
if(!tr[root][]&&!tr[root][]){
clear(root),root=;
return ;
}
if(!(tr[root][]*tr[root][])){
int rt=root;
root=tr[root][]+tr[root][];
fa[root]=,clear(rt);//细节是要先记录root,再更新root,再将原来的root clear
return ;
}
int ok=root;//原来的root
pre(root,x);//求前驱
splay(dist);//Splay到根
fa[tr[ok][]]=root;
tr[root][]=tr[ok][];
clear(ok);up(root);fa[root]=;//clear,更新,细节是要把新根的fa清零
return ;
} }W; int main()
{
N=read();
while(N--){
int o=read(),x;
switch(o){
case :W.insert(W.root,read(),);W.splay(dist);break;
case :W.del(read());break;
case :printf("%d\n",W.QueryX(W.root,read()));break;
case :printf("%d\n",W.QueryK(W.root,read()));break;
case :dist=,W.pre(W.root,read());printf("%d\n",W.v[dist]);break;
case :dist=,W.bac(W.root,read());printf("%d\n",W.v[dist]);break;
}
}
}
Splay初学习的更多相关文章
- clisp, scheme 和 clojure 初学习
clisp, scheme和clojure 初学习 1 clojure "clojure绝对会成为你的编程工具箱里的终极武器" "其他语言可能只是工具,但 Clojure ...
- c# window服务-初学习
window服务-初学习 一.工具: VS2015+NET Framework4.5. 二.操作: 1.新建windows服务的项目: 2.修改windows服务相关内容: 3.预览windows服务 ...
- Python初学习:简单的练习题
Python初学习 一些见到那的练习题: 初级难度 设计一重量转换器,输入以g为单位的数字后,返回换算结果以Kg为单位的结果 中级难度 设计一个求直角三角形斜边长的函数,(以两个直角边为参数,求最长边 ...
- BST,Splay平衡树学习笔记
BST,Splay平衡树学习笔记 1.二叉查找树BST BST是一种二叉树形结构,其特点就在于:每一个非叶子结点的值都大于他的左子树中的任意一个值,并都小于他的右子树中的任意一个值. 2.BST的用处 ...
- [普通平衡树splay]【学习笔记】
参考: http://blog.csdn.net/clove_unique/article/details/50630280 gty课件 找一个好的风格太难了,自己习惯用struct,就强行用stru ...
- Swift初学习
距离swift发布10天了,也简单看了一下swift的语法,个人感觉相对于object-c很是简单明了.Swift的出现并不能说明iOS开发简单了很多,有可能会变得复杂,你需要学习两门编程语言,因为在 ...
- Jquery 插件初学习
参考文章:插件开发精品教程,让你的jQuery提升一个台阶 刚刚学了一下jquery的插件插件开发,写个demo记录.练习一下.毕竟,输出才是最好的学习. 这个也不过是最基础的一个插件写法,只是,自己 ...
- requests库写接口测试框架初学习
学习网址: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-dscpm/ff75b907-415d-4220-89 ...
- 2018.2.21 Python 初学习
折腾了一天,一直在用CMD学习Python写Hello World.偶然间发现可以用Pycharm.也算是给后面想学习的人提个醒,方便省事许多. format()使用方法. age = 20name ...
随机推荐
- 一、异步编程模型(APM)
一.概念 APM即异步编程模式的简写(Asynchronous Programming Model).大家在写代码的时候或者查看.NET 的类库的时候肯定会经常看到和使用以BeginXXX和EndXX ...
- Oracle基础操作
数据库的定义.作用介绍: 什么是数据库? 按照数据结构来组织.存储和管理数据的建立在计算机存储设备上的仓库. 数据库的发展史: 起始于1962年,1968年在IBM出现 数据库在测试过程中的作用: 需 ...
- AngularJs学习笔记--IE Compatibility 兼容老版本IE
原版地址:http://docs.angularjs.org/guide/ie Internet Explorer Compatibility 一.总括 这文章描述Internet Explorer( ...
- Fiddler学习基础(一)
Fiddler官方网站及下载地址:http://www.telerik.com/fiddler 1. Fiddler原理: 作为系统代理,所有的来自微软互联网服务(WinInet)的http请求再到达 ...
- mybatis动态sql语句学习(一)
动态 SQL MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦.拼接的时候要确保不能忘了必要的空格 ...
- 时钟晶振32.768KHz为什么是15分频?
实时时钟晶振为什么选择是32768Hz的晶振,在百度上搜索的话大部分的答案都是说2的15次方是32768,使用这个频率的晶振,人们可以很容易的通过分频电路得到1Hz的计时脉冲.但是话有说回来了,2的整 ...
- sharepoint OOS巨大坑
首先,我们安装的操作系统是windows server 2016 datacenter最新版,然后安装了OOS2016年的那个版本,打好语言包,安装必备软件,所有的步骤都没问题,但是你配置OOS场的时 ...
- 使用 Solr 构建企业级搜索服务器
最近因项目需要一个全文搜索引擎服务, 在考察了Lucene及Solr后,我们选择了Solr. 本文简要记录了基于Solr搭建一个企业搜索服务器的过程.网上的资料太多千篇一律,也可能版本不同,总之在参照 ...
- AtomicStampedReference解决ABA问题
在运用CAS做Lock-Free操作中有一个经典的ABA问题: 线程1准备用CAS将变量的值由A替换为B,在此之前,线程2将变量的值由A替换为C,又由C替换为A,然后线程1执行CAS时发现变量的值 ...
- 遗传算法详解及c++实现
1.什么是遗传算法? 遗传算法是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法.遗传算法是从代表问题可能潜在的解集的一个种群开始的,而一 ...