挖坑待补

前言

感觉我在联赛还差4天的时候学习Splay有点慌,但还是要学一下。

定义

我们先对Splay的数组进行一些定义:

struct node{
int ff,siz,cnt,ch[2],val;
//ff表示父亲,siz表示子树大小,ch表示儿子,cnt表示与这个点权值相同的点的个数,val表示权值。
}t[N<<2];

操作

我们的Splay应该要支持以下几个操作:

  • 插入
  • 删除
  • 查找排名为k的数
  • 查找k的排名
  • 查找k的前驱
  • 查找k的后继
  • 分裂(不会)
  • 合并(启发式合并)

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N=500010;
int root,tot;
inline int gi(){
int sum=0,f=1;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return f*sum;
}
class SplayTree{
private:
struct node{
int ff,siz,cnt,ch[2],val;
//ff表示父亲,siz表示子树大小,ch表示儿子,cnt表示与这个点权值相同的点的个数,val表示权值。
}t[N<<2];
inline void pushup(int x){t[x].siz=t[x].cnt+t[t[x].ch[0]].siz+t[t[x].ch[1]].siz;}
inline void rotate(int x){
int y=t[x].ff,z=t[y].ff;
int k=(x==t[y].ch[1]);
t[z].ch[y==t[z].ch[1]]=x;
t[x].ff=z;
t[y].ch[k]=t[x].ch[k^1];
t[t[x].ch[k^1]].ff=y;
t[x].ch[k^1]=y;
t[y].ff=x;
pushup(y);pushup(x);
}
public:
inline void Splay(int x,int goal){
while(t[x].ff!=goal){
int y=t[x].ff,z=t[y].ff;
if(z!=goal)
(t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y);
rotate(x);
}
if(!goal)root=x;
}
inline void find(int x){
int u=root;
if(!u)return;
while(t[u].val!=x && t[u].ch[x>t[u].val])
u=t[u].ch[x>t[u].val];
Splay(u,0);
}
inline void Insert(int x){
int u=root,ff=0;
while(u && t[u].val!=x){ff=u;u=t[u].ch[x>t[u].val];}
if(u)t[u].cnt++;
else{
u=++tot;
t[u].cnt=t[u].siz=1;t[u].val=x;
t[u].ff=ff;t[u].ch[0]=t[u].ch[1]=0;
if(ff)t[ff].ch[x>t[ff].val]=u;
}
Splay(u,0);
}
inline int Next(int x,int f){//f=1表示后继,f=0表示前驱
find(x);
int u=root;
if(t[u].val>x && f)return u;
if(t[u].val<x && !f)return u;
u=t[u].ch[f];
while(t[u].ch[f^1])u=t[u].ch[f^1];
return u;
}
inline void Delete(int x){
int last=Next(x,0),nxt=Next(x,1);
Splay(last,0);Splay(nxt,last);
int del=t[nxt].ch[0];
if(t[del].cnt>1){t[del].cnt--;Splay(del,0);}
else t[nxt].ch[0]=0;
}
inline int kth(int x){
int u=root;
if(t[u].siz<x)return 0;
while(1){
int y=t[u].ch[0];
if(t[y].siz<x && t[y].siz+t[u].cnt>=x)return t[u].val;
if(t[y].siz>=x)u=y;
else{
x-=t[y].siz+t[u].cnt;
u=t[u].ch[1];
}
}
}
inline int Val(int u){
return t[u].val;
}
inline int ch0size(){
return t[t[root].ch[0]].siz;
}
}Splay;
int main(){
int n=gi();
Splay.Insert(2147483647);
Splay.Insert(-2147483648);
while(n--){
int opt=gi(),x=gi();
if(opt==1)Splay.Insert(x);
if(opt==2)Splay.Delete(x);
if(opt==3){
Splay.find(x);
printf("%d\n",Splay.ch0size());
}
if(opt==4)printf("%d\n",Splay.kth(x+1));
if(opt==5)printf("%d\n",Splay.Val(Splay.Next(x,0)));
if(opt==6)printf("%d\n",Splay.Val(Splay.Next(x,1)));
}
return 0;
}

【总结】 伸展树Splay的更多相关文章

  1. 树-伸展树(Splay Tree)

    伸展树概念 伸展树(Splay Tree)是一种二叉排序树,它能在O(log n)内完成插入.查找和删除操作.它由Daniel Sleator和Robert Tarjan创造. (01) 伸展树属于二 ...

  2. 纸上谈兵: 伸展树 (splay tree)[转]

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢!  我们讨论过,树的搜索效率与树的深度有关.二叉搜索树的深度可能为n,这种情况下,每 ...

  3. K:伸展树(splay tree)

      伸展树(Splay Tree),也叫分裂树,是一种二叉排序树,它能在O(lgN)内完成插入.查找和删除操作.在伸展树上的一般操作都基于伸展操作:假设想要对一个二叉查找树执行一系列的查找操作,为了使 ...

  4. 高级搜索树-伸展树(Splay Tree)

    目录 局部性 双层伸展 查找操作 插入操作 删除操作 性能分析 完整源码 与AVL树一样,伸展树(Splay Tree)也是平衡二叉搜索树的一致,伸展树无需时刻都严格保持整棵树的平衡,也不需要对基本的 ...

  5. 【BBST 之伸展树 (Splay Tree)】

    最近“hiho一下”出了平衡树专题,这周的Splay一直出现RE,应该删除操作指针没处理好,还没找出原因. 不过其他操作运行正常,尝试用它写了一道之前用set做的平衡树的题http://codefor ...

  6. [Splay伸展树]splay树入门级教程

    首先声明,本教程的对象是完全没有接触过splay的OIer,大牛请右上角.. 首先引入一下splay的概念,他的中文名是伸展树,意思差不多就是可以随意翻转的二叉树 PS:百度百科中伸展树读作:BoGa ...

  7. 伸展树Splay【非指针版】

    ·伸展树有以下基本操作(基于一道强大模板题:codevs维护队列): a[]读入的数组;id[]表示当前数组中的元素在树中节点的临时标号;fa[]当前节点的父节点的编号;c[][]类似于Trie,就是 ...

  8. 伸展树(Splay tree)的基本操作与应用

    伸展树的基本操作与应用 [伸展树的基本操作] 伸展树是二叉查找树的一种改进,与二叉查找树一样,伸展树也具有有序性.即伸展树中的每一个节点 x 都满足:该节点左子树中的每一个元素都小于 x,而其右子树中 ...

  9. ZOJ 3765 Lights (zju March I)伸展树Splay

    ZJU 三月月赛题,当时见这个题目没辙,没学过splay,敲了个链表TLE了,所以回来好好学了下Splay,这道题目是伸展树的第二题,对于伸展树的各项操作有了更多的理解,这题不同于上一题的用指针表示整 ...

  10. [数据结构]伸展树(Splay)

    #0.0 写在前面 Splay(伸展树)是较为重要的一种平衡树,理解起来也依旧很容易,但是细节是真的多QnQ,学一次忘一次,还是得用博客加深一下理解( #1.0 Splay! #1.1 基本构架 Sp ...

随机推荐

  1. jQuery插件–jqueryflexselect下拉框自动提示

    原理:用户在文本框中输入一个字符(或输入字符的首字母),然后利用ajax,从后台服务器中进行检索,组装后并返回到页面,页面通过javascript进行解析,在一个层里面显示出来. 类似的效果如下: & ...

  2. MySQL数据库篇之完整性约束和表关系

    主要内容: 一.完整性约束 二.表关系 1️⃣ 完整性约束 (1)何为完整性约束? 约束条件与数据类型的宽度一样,都是可选参数. 作用:用于保证数据的完整性和一致性 (2)分类主要有以下五类: 1.n ...

  3. 查看MSSQL数据库每个表占用的空间大小

    需要查看数据库表的大小,查询SQL Server联机从书得到如下语句: sp_spaceused 显示行数.保留的磁盘空间以及当前数据库中的表所使用的磁盘空间,或显示由整个数据库保留和使用的磁盘空间. ...

  4. 英文单词cipher 和password的区别,用法有什么不同,

    ['saɪfə(r)] cipher 指一套密码系统,比如电影<风声>中破译的那个系统叫cipher:password 则指进入的指令,比如你的qq密码,电脑密码等叫password.总之 ...

  5. ZPL语言说明文档

    ■格式命令(format commands) 以︿开始 用于设定标签格式与数据 多条格式指令按顺序执行 ■控制指令(control commands) 以~开始 迫使打印机立即执行某一个指令的操作 可 ...

  6. IPMI命令

    yum -y install ipmitool/etc/init.d/ipmi start ipmitool -I open lan set 1 ipaddr 172.16.8.33ipmitool ...

  7. 基于mosquitto的MQTT服务器---SSL/TLS 单向认证+双向认证

    基于mosquitto的MQTT服务器---SSL/TLS 单向认证+双向认证 摘自:https://blog.csdn.net/ty1121466568/article/details/811184 ...

  8. IDEA设置与快捷键记录

    一:代码提示大小写设置 二:设置代码检查等级 IntelliJ IDEA 对于编辑大文件并没有太大优势,很卡,原因就是它有各种检查,这样是非常耗内存和 CPU 的,所以为了能加快大文件的读写,我一般会 ...

  9. C# Winform 跨线程更新UI控件常用方法总结(转)

    出处:http://www.tuicool.com/articles/FNzURb 概述 C#Winform编程中,跨线程直接更新UI控件的做法是不正确的,会时常出现“线程间操作无效: 从不是创建控件 ...

  10. 使用word 2007 发布csdn博客

    目前大部分的博客作者在写博客这件事情上都会遇到以下3个痛点:1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.2.发布到博客或公众号平台 ...