因为学了treap,不想弃坑去学splay,终于理解了无旋treap...

好像普通treap没卵用。。。(再次大雾)

简单说一下思想免得以后忘记。普通treap因为带旋转操作似乎没卵用,而无旋treap可以不旋转。

经典地不能再经典的例题

 

题目描述

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

  1. 插入x数

  2. 删除x数(若有多个相同的数,因只删除一个)

  3. 查询x数的排名(若有多个相同的数,因输出最小的排名)

  4. 查询排名为x的数

  5. 求x的前驱(前驱定义为小于x,且最大的数)

  6. 求x的后继(后继定义为大于x,且最小的数)

输入输出格式

输入格式:

第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)

输出格式:

对于操作3,4,5,6每行输出一个数,表示对应答案

输入输出样例

输入样例#1:

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
输出样例#1:

106465
84185
492737

说明

时空限制:1000ms,128M

1.n的数据范围:n<=100000

2.每个数的数据范围:[-1e7,1e7]

无旋treap最基本的操作就是merge和split。修改都得靠这个。首先说一下merge和split的操作方法。

merge:给你两个平衡树a和b,让你合并它们,但b中所有权值都得大于a中所有权值以维护treap性质。如果是tree只需要建个根节点然后连两条边,但无法维护heap性质。其实操作也很简单,如果a的rand值小于b的rand值,则merge(a.rs,b),否则merge(a,b.ls)。

split:将平衡树a分成两个,一个是1~K名,一个是K+1~size名,返回两个树的根,我存在了一个pair中。记左子树size为s,如果k==s则两根就是左儿子和根,如果k==s+1则两根就是根和右儿子。若都不是,继续向下递归,那个就参照以下查询排名的操作。注意split要将儿子设为0

那么基本操作怎么实现???

查询排名、查询排名为x的数、查询前驱后继代码基本不变,只是要注意这里需要合并分离所以不可以记录出现次数要新开一个数,否则后果自行脑补。

插入操作:先查询这个数x的排名K,然后把treap分成两个treap,即执行split(root,K),得到两根a,b。再合并两次,即执行root=merge(a,点的新编号),root=merge(root,b)(注意要重设root)

删除操作:也差不多。先查询排名K,然后把treap分成三个treap,分别为a=1~K-1,b=K,c=K+1~n,要删去K,只需再合并a,c子树即可

不旋转应该就可以维护一些别的好东西了

然而并不会

然后附上普通平衡树的AC代码:

 // It is made by XZZ
#include<cstdio>
#include<algorithm>
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define vd void
#define mp make_pair
typedef long long ll;
il int gi(){
rg int x=,f=;rg char ch=getchar();
while(ch<''||ch>'')f=ch=='-'?-:f,ch=getchar();
while(ch>=''&&ch<='')x=x*+ch-'',ch=getchar();
return x*f;
}
#define Now tree[now]
struct node{int ls,rs,value,rand,size;}tree[];
int root,siz;
int seed=++;//mou shen ben xue hao+mou da lao xue hao+mou ju ruo xue hao
il int Rand(){return seed=seed*%;}
il vd reset(int now){Now.size=tree[Now.ls].size+tree[Now.rs].size+;}
il int merge(int a,int b){
if(!a||!b)return a|b;
if(tree[a].rand<tree[b].rand){tree[a].rs=merge(tree[a].rs,b),reset(a);return a;}
else {tree[b].ls=merge(a,tree[b].ls),reset(b);return b;}
}
il pair<int,int>split(int now,int num){
if(!now)return mp(,);
int ls=Now.ls,rs=Now.rs;
if(num==tree[ls].size){Now.ls=,reset(now);return mp(ls,now);}
if(num==tree[ls].size+){Now.rs=,reset(now);return mp(now,rs);}
if(num<tree[ls].size){
pair<int,int>T=split(ls,num);
Now.ls=T.second,reset(now);
return mp(T.first,now);
}else{
pair<int,int>T=split(rs,num-tree[ls].size-);
Now.rs=T.first,reset(now);
return mp(now,T.second);
}
}
il int getrank(int now,int num){
int ret=,t=1e9;
while(now){
if(num==Now.value)t=min(t,ret+tree[Now.ls].size+);
if(num<=Now.value)now=Now.ls;
else ret+=tree[Now.ls].size+,now=Now.rs;
}
return t==1e9?ret:t;
}
il int getnum(int now,int num){
while(){
if(tree[Now.ls].size==num-)return Now.value;
if(tree[Now.ls].size>num-)now=Now.ls;
else num-=tree[Now.ls].size+,now=Now.rs;
}
}
il int lower(int now,int num){
int ret;
while(now)if(tree[now].value<num)ret=tree[now].value,now=Now.rs;
else now=Now.ls;
return ret;
}
il int upper(int now,int num){
int ret;
while(now)if(tree[now].value>num)ret=tree[now].value,now=Now.ls;
else now=Now.rs;
return ret;
}
il vd ins(int num){
int Rank=getrank(root,num),now;
pair<int,int>tmp=split(root,Rank);
now=++siz;
Now.value=num,Now.rand=Rand(),Now.size=;
root=merge(tmp.first,siz);
root=merge(root,tmp.second);
}
il vd del(int num){
int Rank=getrank(root,num);
pair<int,int>t1=split(root,Rank),t2=split(t1.first,Rank-);
root=merge(t2.first,t1.second);
}
int main(){
int n=gi(),opt,x;
while(n--){
opt=gi(),x=gi();
switch(opt){
case :ins(x);break;
case :del(x);break;
case :printf("%d\n",getrank(root,x));break;
case :printf("%d\n",getnum(root,x));break;
case :printf("%d\n",lower(root,x));break;
case :printf("%d\n",upper(root,x));break;
}
}
return ;
}

还有一篇博客代码写的不错,这是链接

无旋treap的简单思想以及模板的更多相关文章

  1. 模板 - 数据结构 - 可持久化无旋Treap/PersistentFHQTreap

    有可能当树中有键值相同的节点时,貌似是要对Split和Merge均进行复制的,本人实测:只在Split的时候复制得到了一个WA,但只在Merge的时候复制还是AC,可能是恰好又躲过去了.有人说假如确保 ...

  2. 模板 - 无旋Treap

    一般而言作为一棵平衡树只需要插入,删除,值求排名,排名求值,前驱,后继,六个接口. #include<bits/stdc++.h> using namespace std; typedef ...

  3. 洛谷 - P3391 【模板】文艺平衡树(Splay) - 无旋Treap

    https://www.luogu.org/problem/P3391 使用无旋Treap维护序列,注意的是按顺序插入的序列,所以Insert实际上简化成直接root和Merge合并,但是假如要在序列 ...

  4. [转载]无旋treap:从好奇到入门(例题:bzoj3224 普通平衡树)

    转载自ZZH大佬,原文:http://www.cnblogs.com/LadyLex/p/7182491.html 今天我们来学习一种新的数据结构:无旋treap.它和splay一样支持区间操作,和t ...

  5. [您有新的未分配科技点]无旋treap:从好奇到入门(例题:bzoj3224 普通平衡树)

    今天我们来学习一种新的数据结构:无旋treap.它和splay一样支持区间操作,和treap一样简单易懂,同时还支持可持久化. 无旋treap的节点定义和treap一样,都要同时满足树性质和堆性质,我 ...

  6. 【算法学习】Fhq-Treap(无旋Treap)

    Treap——大名鼎鼎的随机二叉查找树,以优异的性能和简单的实现在OIer们中广泛流传. 这篇blog介绍一种不需要旋转操作来维护的Treap,即无旋Treap,也称Fhq-Treap. 它的巧妙之处 ...

  7. 无旋treap的区间操作实现

    最近真的不爽...一道维修数列就做了我1上午+下午1h+1晚上+晚上1h+上午2h... 一道不错的自虐题... 由于这一片主要讲思想,代码我放这里了 不会无旋treap的童鞋可以进这里 呵呵... ...

  8. 浅谈无旋treap(fhq_treap)

    一.简介 无旋Treap(fhq_treap),是一种不用旋转的treap,其代码复杂度不高,应用范围广(能代替普通treap和splay的所有功能),是一种极其强大的平衡树. 无旋Treap是一个叫 ...

  9. [转载]无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )

    转自ZZH大佬,原文:http://www.cnblogs.com/LadyLex/p/7182631.html 1500: [NOI2005]维修数列 Time Limit: 10 Sec  Mem ...

随机推荐

  1. BZOJ1049:[HAOI2006]数字序列(DP)

    Description 现在我们有一个长度为n的整数序列A.但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列. 但是不希望改变过多的数,也不希望改变的幅度太大. Input 第一行包含一个 ...

  2. BZOJ1563:[NOI2009]诗人小G(决策单调性DP)

    Description Input Output 对于每组数据,若最小的不协调度不超过1018,则第一行一个数表示不协调度若最小的不协调度超过1018,则输出"Too hard to arr ...

  3. 随手练——洛谷-P1002 过河卒(动态规划入门)

    题目链接:https://www.luogu.org/problemnew/show/P1002 题目还算良心,提醒了结果可能很大,确实爆了int范围, 这是一开始写的版本,用递归做的,先给地图做标记 ...

  4. [Python 模块] logging模块、Logger类

    logging模块: 标准库里面的logging模块,在前面学习线程安全时曾用来解决print被打断的问题,这里会介绍logging模块的功能. logging模块是线程安全的,不需要客户做任何特殊的 ...

  5. 关于selenium获取token sessionid

    # 获取sessionid def get_sessionid(self): # 是要从localStorage中获取还是要从sessionStorage中获取,具体看目标系统存到哪个中 # wind ...

  6. PL/SQL Developer修改窗口字体和大小

    工具 → 首选项 → 字体 → 选择, 然后自己调节设置

  7. [USACO08JAN]电话线$Telephone \ \ Lines$(图论$+SPFA+$ 二分答案)

    #\(\mathcal{\color{red}{Description}}\) \(Link\) 给定一个图,请你求出在把其中自由选择的\(k\)条的权值都置为零的情况下,图中\(1-N\)最短路上的 ...

  8. linux下安装perl

    1.在官网  http://www.perl.org/get.html  下载perl安装包 2.上传服务器并解压 3../Configure -des -Dprefix=安装目录 4.make&am ...

  9. Spring 约束文件配置

    1.引入jar包 2.新建applicationContext.xml配置文件 位置随意,建议放在src目录下 新建的空xml文件,写入一对beans标签 3.打开Windows-->Prefe ...

  10. 如何使用gitbash 把你的代码托管到github

    1.如果你没有创建仓库 mkdir vuex-playList cd vuex-playList git init touch README.md git add README.md git comm ...