Splay版本的会补。。。

在学了2个小时Splay之后深感Treap的优越

特地又花了20分钟打了个Treap

至于这些平衡树的优缺点 可以用平衡方式来直观的感受到

现在平衡树们面对着这样的一个问题:“二叉搜索树退化成O(n)”怎么办

Splay说:下面退不退化我不管 我把要查询的点转到根节点上

替罪羊树说:我看哪块不平衡了 我就把它拍扁重建弄成平衡的

SBT说:我旋转强行让深度为logn

RBT说:我手动给每个点打标签让他们出现各种性质然后旋转

而Treap说:在座的各位都是辣鸡 普通的二叉查找树对于随机数据不是平衡的吗?我随机给每个点分派一个数据 让整棵树对于这个随机数据平衡

Splay&替罪羊树&SBT&RBT:Orz

大概就是这样吧

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn=;
const int inf=1e9;
const int mod=;
inline int read()
{
int x=,f=;
char ch=getchar();
while(!isdigit(ch)){if(ch=='')f=-f;ch=getchar();}
while(isdigit(ch)){x=*x+ch-'';ch=getchar();}
return x*f;
}
struct Treenode
{
int l,r,v,rnd,size,w;
};
inline int ran()
{
static int seed=;
seed+=(seed<<)+;
return seed;
}
struct Treap
{
Treenode tr[maxn];
int root,Size,ans;
inline void update(int k){tr[k].size=tr[tr[k].l].size+tr[tr[k].r].size+tr[k].w;}
inline void Leftr(int &k)
{
int t=tr[k].r;
tr[k].r=tr[t].l;
tr[t].l=k;
tr[t].size=tr[k].size;
update(k);
k=t;
}
inline void Rightr(int &k)
{
int t=tr[k].l;
tr[k].l=tr[t].r;
tr[t].r=k;
tr[t].size=tr[k].size;
update(k);
k=t;
}
inline void insert(int &k,int x)
{
if(k==)
{
Size++;
k=Size;
tr[k].size=tr[k].w= ;
tr[k].v=x;
tr[k].rnd=ran();
return;
}
tr[k].size++;
if(tr[k].v==x)tr[k].w++;
else if(x>tr[k].v)
{
insert(tr[k].r,x) ;
if(tr[tr[k].r].rnd<tr[k].rnd)Leftr(k) ;
}
else
{
insert(tr[k].l,x) ;
if(tr[tr[k].l].rnd<tr[k].rnd)Rightr(k) ;
}
}
inline void del(int &k,int x)
{
if(k==) return;
if(tr[k].v==x)
{
if(tr[k].w>) {tr[k].w--,tr[k].size--;return;}
if(tr[k].l*tr[k].r==)k=tr[k].l+tr[k].r;
else if(tr[tr[k].l].rnd<tr[tr[k].r].rnd){Rightr(k);del(k,x);}
else{Leftr(k);del(k,x);}
}
else if(x>tr[k].v){tr[k].size--;del(tr[k].r,x);}
else{tr[k].size--;del(tr[k].l,x);}
}
inline int query_rank(int k,int x)
{
if(k==) return ;
if(tr[k].v==x) return tr[tr[k].l].size+ ;
else if(x>tr[k].v) return tr[tr[k].l].size+tr[k].w+query_rank(tr[k].r,x) ;
else return query_rank(tr[k].l,x) ;
}
inline int query_num(int k,int x)
{
if(k==) return ;
if(x<=tr[tr[k].l].size)return query_num(tr[k].l ,x) ;
else if(x>tr[tr[k].l].size+tr[k].w)return query_num(tr[k].r,x-tr[tr[k].l].size-tr[k].w);
else return tr[k].v;
}
inline void query_pro(int k,int x)
{
if(k==)return;
if(tr[k].v<x)
{
ans=k ;
query_pro(tr[k].r,x);
}
else query_pro(tr[k].l,x);
}
inline void query_sub(int k,int x)
{
if(k==) return;
if(tr[k].v>x)
{
ans=k;
query_sub(tr[k].l,x);
}
else query_sub(tr[k].r,x);
}
}treap; int main()
{
int n;
scanf("%d",&n);
int op,x;
for(int i=;i<=n;i++)
{
scanf("%d%d",&op,&x);
if(op==)treap.insert(treap.root,x);
if(op==)treap.del(treap.root,x);
if(op==)printf("%d\n",treap.query_rank(treap.root,x));
if(op==)printf("%d\n",treap.query_num(treap.root,x));
if(op==){treap.ans=;treap.query_pro(treap.root,x);printf("%d\n",treap.tr[treap.ans].v);}
if(op==){treap.ans=;treap.query_sub(treap.root,x);printf("%d\n",treap.tr[treap.ans].v);}
}
}

bzoj3224Treap的更多相关文章

随机推荐

  1. 设置tableView背景颜色

    [treeTableView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight] ...

  2. css3中font-face属性的用法详解

    @font-face是CSS3中的一个模块,他主要是把自己定义的Web字体嵌入到你的网页中,随着@font-face模块的出现,我们在Web的开发中使用字体不怕只能使用Web安全字体,你们当中或许有许 ...

  3. os模块,sys模块

    # os模块 # os模块是与操作系统交互的一个接口 ''' 和工作目录相关: os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径(在什么地方执行就是那个文件的路径) os ...

  4. js验证金额是否符合要求的正则表达式

    正则的只是就不在这里重复的讲了,直接上代码 var mny = /^(((([1-9]([0-9]{0,8}))|0)\.([0-9]{1,2}))|([1-9]([0-9]{0,8})))$/; m ...

  5. pip源提示“not a trusted or secure host” 解决

    问题:The repository located at mirrors.aliyun.com is not a trusted or secure host and is being ignored ...

  6. VC++MFC对话框程序中给对话添加背景图片

    VC对话框怎么显示背景图片呢.在MFC中实现背景图片,不像C#应用程序那么简单.今天就和朋友们说说如何在VC界面中设置背景图片 ^_^   工具/原料 Visual C++ 2010 方法一:用Pic ...

  7. HDFS上传机制

  8. html5 (新一代的html)

    简介 h5的新特性: cavas / video / audio / cache / element / form 最小的h5文档: <!DOCTYPE html> <html> ...

  9. Spring 拦截器——HandlerInterceptor

    采用Spring拦截器的方式进行业务处理.HandlerInterceptor拦截器常见的用途有: 1.日志记录:记录请求信息的日志,以便进行信息监控.信息统计.计算PV(Page View)等. 2 ...

  10. next()和nextLine()的区别

    众所周知,在Java中输入字符串有两种方法,就是next()和nextLine(),今天研究了一下其中的区别. 首先,nextLine()的输入是碰到回车就终止输入,而next()方法是碰到空格,回车 ...