挖坑待补

前言

感觉我在联赛还差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. partial分部类

    意义 1.源代码控制 2.将一个类或结构分成不同的逻辑单元 3.代码拆分

  2. FreeSWITCH 启用多域(多租户)的配置

    如果将FreeSWITCH用于云端, 支持大规模并发呼叫, 就要用到 多域/多租户 技术了, FreeSWITCH 本身可以直接支持. 每个域可以单独, 拥有相同的分机号也互相打不通, 各自线路, I ...

  3. Uniform & Attribute & Varying

    [Uniform & Attribute & Varying] 顶点着色器的输入变量用关键字“attribute”来限定. 片段着色器的输入变量(它和顶点着色器的输出变量相对应)用关键 ...

  4. PHPexcle案例

    下面是总结的几个使用方法 include 'PHPExcel.php'; include 'PHPExcel/Writer/Excel2007.php'; //或者include 'PHPExcel/ ...

  5. Python_12-线程编程

    1.1    Python中的线程使用1.1.1 函数式1.2    创建threading.Thread的子类来包装一个线程对象1.2.1 threading.Thread类的使用1.3    线程 ...

  6. 【POJ1811】Prime Test

    [题目大意] 若n是素数,输出“Prime”,否则输出n的最小素因子,(n<=2^54) [题解] 和bzoj3667差不多,知识这道题没那么坑. 直接上Pollord_Rho和Rabin_Mi ...

  7. shiro 集成spring 使用 redis作为缓存 学习记录(六)

    1.在applicationContext-redis.xml配置文件中增加如下: 申明一个cacheManager对象 用来注入到  shiro的   securityManager 属性  cac ...

  8. Linux发送邮件

    以下是自己收集的实用Linux下简单配置外部邮箱发送邮件的方法: 1.配置/etc/mail.rc,使用mail命令 # vim /etc/mail.rc ###调用外部邮箱   set from=t ...

  9. Web测试实践-任务进度-Day01

    任务安排 说明:小组全体成员都参与了会议,对该实践进行分析以及对实践任务的拆分以及进行了任务的分配. 小组成员 华同学.郭同学.覃同学.刘同学.穆同学.沈同学 阶段划分 阶段1:评测被测系统 1.对被 ...

  10. CMDB小练习

    为什么要用CMDB? 因为公司之前统计资产信息用的是excel表格,随着业务的增加和信息的变更,这个表格变得越来越乱,所以我们就想着编写出一套自动管理资产信息的系统,实现自动管理资产信息 三种方案? ...