无旋treap的简单思想以及模板
因为学了treap,不想弃坑去学splay,终于理解了无旋treap...
好像普通treap没卵用。。。(再次大雾)
简单说一下思想免得以后忘记。普通treap因为带旋转操作似乎没卵用,而无旋treap可以不旋转。
经典地不能再经典的例题
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
插入x数
删除x数(若有多个相同的数,因只删除一个)
查询x数的排名(若有多个相同的数,因输出最小的排名)
查询排名为x的数
求x的前驱(前驱定义为小于x,且最大的数)
- 求x的后继(后继定义为大于x,且最小的数)
输入输出格式
输入格式:
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
输出格式:
对于操作3,4,5,6每行输出一个数,表示对应答案
输入输出样例
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
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的简单思想以及模板的更多相关文章
- 模板 - 数据结构 - 可持久化无旋Treap/PersistentFHQTreap
有可能当树中有键值相同的节点时,貌似是要对Split和Merge均进行复制的,本人实测:只在Split的时候复制得到了一个WA,但只在Merge的时候复制还是AC,可能是恰好又躲过去了.有人说假如确保 ...
- 模板 - 无旋Treap
一般而言作为一棵平衡树只需要插入,删除,值求排名,排名求值,前驱,后继,六个接口. #include<bits/stdc++.h> using namespace std; typedef ...
- 洛谷 - P3391 【模板】文艺平衡树(Splay) - 无旋Treap
https://www.luogu.org/problem/P3391 使用无旋Treap维护序列,注意的是按顺序插入的序列,所以Insert实际上简化成直接root和Merge合并,但是假如要在序列 ...
- [转载]无旋treap:从好奇到入门(例题:bzoj3224 普通平衡树)
转载自ZZH大佬,原文:http://www.cnblogs.com/LadyLex/p/7182491.html 今天我们来学习一种新的数据结构:无旋treap.它和splay一样支持区间操作,和t ...
- [您有新的未分配科技点]无旋treap:从好奇到入门(例题:bzoj3224 普通平衡树)
今天我们来学习一种新的数据结构:无旋treap.它和splay一样支持区间操作,和treap一样简单易懂,同时还支持可持久化. 无旋treap的节点定义和treap一样,都要同时满足树性质和堆性质,我 ...
- 【算法学习】Fhq-Treap(无旋Treap)
Treap——大名鼎鼎的随机二叉查找树,以优异的性能和简单的实现在OIer们中广泛流传. 这篇blog介绍一种不需要旋转操作来维护的Treap,即无旋Treap,也称Fhq-Treap. 它的巧妙之处 ...
- 无旋treap的区间操作实现
最近真的不爽...一道维修数列就做了我1上午+下午1h+1晚上+晚上1h+上午2h... 一道不错的自虐题... 由于这一片主要讲思想,代码我放这里了 不会无旋treap的童鞋可以进这里 呵呵... ...
- 浅谈无旋treap(fhq_treap)
一.简介 无旋Treap(fhq_treap),是一种不用旋转的treap,其代码复杂度不高,应用范围广(能代替普通treap和splay的所有功能),是一种极其强大的平衡树. 无旋Treap是一个叫 ...
- [转载]无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )
转自ZZH大佬,原文:http://www.cnblogs.com/LadyLex/p/7182631.html 1500: [NOI2005]维修数列 Time Limit: 10 Sec Mem ...
随机推荐
- [CQOI2017]小Q的表格
题目 神仙题,神仙题 这是一道很适合盯着发呆的题目 看到这个规律 \[ f(a,b)=f(b,a) \] \[ b\times f(a,a+b)=(a+b)\times f(a,b) \] 这也没什么 ...
- Django中模型(二)
Django中模型(二) 三.定义模型 1.模型.属性.表.字段间的关系: 一个模型类在数据库中对应一张表:在模型类中定义的属性,对应该模型对照表中的字段. 2.定义属性 A.概述 ·django根据 ...
- [转载] MySQL 注入攻击与防御
MySQL 注入攻击与防御 2017-04-21 16:19:3454921次阅读0 作者:rootclay 预估稿费:500RMB 投稿方式:发送邮件至linwei#360.cn,或登陆网页 ...
- 人人开源之代码生成器(renren-generator)
本篇文章,主要包含三个部分,介绍.代码生成演示.代码分析(不会很深入)等 三个部分足以让你学会使用,实际生产可能遇到的问题不会在这遇到. 代码生成器的作用在于提高开发效率.但是这个代码生成器仍有其局限 ...
- sqoop2启动job报错
set option --name verbose --value true #打开报错详情输出 Exception has occurred during processing command ...
- PAT——1034. 有理数四则运算
本题要求编写程序,计算2个有理数的和.差.积.商. 输入格式: 输入在一行中按照“a1/b1 a2/b2”的格式给出两个分数形式的有理数,其中分子和分母全是整型范围内的整数,负号只可能出现在分子前,分 ...
- iOS:图片相关(18-02-12更)
1.图片显示相关 1).图片聊天背景拉伸不失真 2).捏合.双击.下拉缩放 3).Banner.相册 4).动画 2.图片操作相关 1).获取.下载图片(分享.传图片用) 2).保存UIImage到本 ...
- 使用Mybatis连接到Mysql报错,WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be esta
在Eclipse中使用springboot整合Mybatis,连接到5.7版本Mysql报错WARN: Establishing SSL connection without server's ide ...
- Mysql双向同步热备份设置
1.环境描述. 主机:103.241.49.137(A) 主机:103.240.182.191(B) MYSQL 版本为5.1.112.授权用户.(本人比较懒,直接用的root 跳过这一步)A:mys ...
- Delphi判断某个类是否实现了某个接口
通过TObject.GetInterface可以获得对象的实例实现某个接口,前提条件是必须实例化对象后才能运行GetInterface 下面的方法可获取类是否实现了某个接口,并返回接口的偏移: fun ...