因为学了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. Excel对同样项求和

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/yeweiouyang/article/details/32107423 方法一(SUMIF公式求和) ...

  2. 安装LAMP PHP的./configure 參数,未出现MYSQ

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/default7/article/details/30613781 编译參数: ./configure ...

  3. CF284A Cows and Primitive Roots

    嘟嘟嘟 这道题就是求一个奇素数\(p\)的原根数量. 公式是\(\varphi(\varphi(p))\).又因为\(p\)是质数,所以就是\(\varphi(p - 1)\). (证明啥的我不会-- ...

  4. C#关于排程举一个小例子

    执行后程序会一直执行. 下面是一个例子

  5. 404 Note Found队-现场编程

    目录 组员职责分工 github 的提交日志截图 程序运行截图 程序运行环境 GUI界面 基础功能实现 运行视频 LCG算法 过滤(降权)算法 算法思路 红黑树 附加功能一 背景 实现 附加功能二(迭 ...

  6. 大话Linux内核中锁机制之内存屏障、读写自旋锁及顺序锁

    大话Linux内核中锁机制之内存屏障.读写自旋锁及顺序锁 在上一篇博文中笔者讨论了关于原子操作和自旋锁的相关内容,本篇博文将继续锁机制的讨论,包括内存屏障.读写自旋锁以及顺序锁的相关内容.下面首先讨论 ...

  7. 什么是Spring框架? Spring框架有哪些主要的模块?

    Spring框架是一个为java应用程序的开发提供了综合,广泛的基础性支持的java平台.Spring帮助开发者解决了开发中基础性的问题,使得开发人员可以专注于应用程序的开发.Spring框架本身亦是 ...

  8. iOS学小程序从0到发布(适合iOS开发看)

    Emmmm,最近一波失业潮.富某康.某团.摩某.京某.知某.某浪.58 某大面积裁员,那么在这个千钧一发之际,单纯iOS开发也着实不好过,回过头看一下,裁掉的都是单一选手,为了节约成本公司留下的都是身 ...

  9. Mysql 查询是否锁表

    1.查询是否锁表show OPEN TABLES where In_use > 0; 2.查询进程 show processlist 查询到相对应的进程===然后 kill id 补充:查看正在 ...

  10. JQ+css3 导航栏到底部上移

    导航栏 .navigation { position: fixed; bottom: 100px; right: 100px; z-index:; } .navigation { transition ...