【模板】非旋转Treap
Treap,也叫做树堆,是指有一个随机附加域满足堆的性质的二叉搜索树。
如果一棵二叉搜索树插入节点的顺序是随机的,那我们得到的二叉搜索树在大多数情况下是平衡的,期望高度是log(n).
但有些情况下我们并不能得知所有待插入节点,打乱以后再插入,这时我们需要给二叉搜索树加上一个随机附加域,并使这个随机附加域(优先级)满足堆的性质,以此来实现“乱序插入”的想法,使二叉搜索树保持平衡。
Treap可以满足的序列操作:
1,插入一个数x
2,删除一个数x
3,查询x的排名
4,查询排名为x的数
5,查询x的前驱
6,查询x的后继
Treap的基本操作
1,newnode新建节点
2,split分裂 把Treap按照权值分割为两部分
3,merge合并 把Treap的两部分进行合并
4,insert插入 把Treap按照插入的权值Val分裂为两部分,然后merge左边和新点,再merge新的左边和右边
5,delete删除 把Treap分裂两次,中间那部分不管它,把两边merge一下
#include<cstdio>
#include<algorithm>
#define ls (a[u].l)
#define rs (a[u].r)
using namespace std;
const int maxn=;
int n,k,x,y,z,v,tot,root;
struct treap{int l,r,v,rnd,size;}a[maxn];
inline void read(int &k){
k=; int f=; char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(''<=c&&c<='')k=k*+c-'',c=getchar();
k*=f;
}
void newnode(int v){a[++tot]=(treap){,,v,rand()+,};}
void update(int u){a[u].size=a[ls].size+a[rs].size+;}
void split(int u,int k,int &x,int &y){
if(!k){x=; y=u; return;}
if(a[u].size==k){x=u; y=; return;}
if(a[ls].size>=k) split(ls,k,x,ls),y=u;
else split(rs,k-a[ls].size-,rs,y),x=u;
update(u);
}
int merge(int x,int y){
if(!(x*y)) return x+y;
if(a[x].rnd>a[y].rnd){
a[y].l=merge(x,a[y].l); update(y); return y;
}
else{
a[x].r=merge(a[x].r,y); update(x); return x;
}
}
int qrank(int u,int val){
if(!u) return ;
if(a[u].v>=val) return qrank(ls,val);
return qrank(rs,val)+a[ls].size+;
}
int qval(int u,int k){
if(a[ls].size+==k) return a[u].v;
return a[ls].size>=k?qval(ls,k):qval(rs,k-a[ls].size-);
}
int main(){
srand(); root=tot=; a[root].v=2e9; a[root].size=;
read(n);
while(n--){
read(k); read(v);
if(k==){//插入
split(root,qrank(root,v),x,y);
newnode(v); root=merge(merge(x,tot),y);
}
if(k==){//删除
split(root,qrank(root,v),x,y);
split(y,,z,y); root=merge(x,y);
}
if(k==) printf("%d\n",qrank(root,v)+);//查询x的排名
if(k==) printf("%d\n",qval(root,v));//查询排名为x的数
if(k==) printf("%d\n",qval(root,qrank(root,v)));//查询x的前驱
if(k==) printf("%d\n",qval(root,qrank(root,v+)+));//查询x的后继
}
return ;
}
#include<cstdio>
#include<algorithm>
#define ls (a[u].l)
#define rs (a[u].r)
using namespace std;
const int maxn=;
int n,k,x,y,z,v,tot,root;
struct treap{int l,r,v,rnd,size;}a[maxn];
inline int read(){
int k=,f=; char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(''<=c&&c<='')k=k*+c-'',c=getchar();
return k*f;
}
void newnode(int val){a[++tot]=(treap){,,val,rand()+,};}
void update(int u){a[u].size=a[ls].size+a[rs].size+;}
void split(int u,int k,int &x,int &y){
if(!k){x=; y=u; return;}
if(a[u].size==k){x=u; y=; return;}
if(a[ls].size>=k) split(ls,k,x,ls),y=u;
else split(rs,k-a[ls].size-,rs,y),x=u;
update(u);
}
int merge(int x,int y){
if(!x||!y) return x+y;
if(a[x].rnd<a[y].rnd){a[x].r=merge(a[x].r,y); update(x); return x;}
else{a[y].l=merge(x,a[y].l); update(y); return y;}
}
int qrank(int u,int val){
if(!u) return ;
return a[u].v>=val?qrank(ls,val):qrank(rs,val)+a[ls].size+;
}
int qval(int u,int k){
if(a[ls].size+==k) return a[u].v;
return a[ls].size>=k?qval(ls,k):qval(rs,k-a[ls].size-);
}
int main(){
srand(); a[root=tot=]=(treap){,,2e9,,};
n=read();
while(n--){
k=read(); v=read();
if(k==){
split(root,qrank(root,v),x,y);
newnode(v); root=merge(merge(x,tot),y);
}
if(k==){
split(root,qrank(root,v),x,y); split(y,,z,y);
root=merge(x,y);
}
if(k==) printf("%d\n",qrank(root,v)+);
if(k==) printf("%d\n",qval(root,v));
if(k==) printf("%d\n",qval(root,qrank(root,v)));
if(k==) printf("%d\n",qval(root,qrank(root,v+)+));
}
return ;
}
洛谷3369
【模板】非旋转Treap的更多相关文章
- BZOJ5063旅游——非旋转treap
题目描述 小奇成功打开了大科学家的电脑. 大科学家打算前往n处景点旅游,他用一个序列来维护它们之间的顺序.初 始时,序列为1,2,...,n. 接着,大科学家进行m次操作来打乱顺序.每次操作有6步: ...
- BZOJ1251序列终结者——非旋转treap
题目描述 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列 要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技 ...
- 平衡树及笛卡尔树讲解(旋转treap,非旋转treap,splay,替罪羊树及可持久化)
在刷了许多道平衡树的题之后,对平衡树有了较为深入的理解,在这里和大家分享一下,希望对大家学习平衡树能有帮助. 平衡树有好多种,比如treap,splay,红黑树,STL中的set.在这里只介绍几种常用 ...
- 旋转/非旋转treap的简单操作
treap(树堆) 是在二叉搜索树的基础上,通过维护随机附加域,使其满足堆性质,从而使树相对平衡的二叉树: 为什么可以这样呢? 因为在维护堆的时候可以同时保证搜索树的性质: (比如当一棵树的一个域满足 ...
- 非旋转 treap
其实之前学过一次非旋转 treap,但是全忘光了,今天复习一下. 洛谷 P3369 [模板]普通平衡树 code: #include <bits/stdc++.h> #define N 1 ...
- [bzoj3173]最长上升子序列_非旋转Treap
最长上升子序列 bzoj-3173 题目大意:有1-n,n个数,第i次操作是将i加入到原有序列中制定的位置,后查询当前序列中最长上升子序列长度. 注释:1<=n<=10,000,开始序列为 ...
- 关于非旋转treap的学习
非旋转treap的操作基于split和merge操作,其余操作和普通平衡树一样,复杂度保证方式与旋转treap差不多,都是基于一个随机的参数,这样构出的树树高为\(logn\) split 作用:将原 ...
- [Codeforces702F]T-Shirts——非旋转treap+贪心
题目链接: Codeforces702F 题目大意:有$n$种T恤,每种有一个价格$c_{i}$和品质$q_{i}$且每种数量无限.现在有$m$个人,第$i$个人有$v_{i}$元,每人每次会买他能买 ...
- BZOJ3223文艺平衡树——非旋转treap
此为平衡树系列第二道:文艺平衡树您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作: 翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 ...
- BZOJ3224普通平衡树——非旋转treap
题目: 此为平衡树系列第一道:普通平衡树您需要写一种数据结构,来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数, ...
随机推荐
- node.js下操作cookie
cookie,又是cookie.工作中与cookie打交道很多次,不过时间跨度也大,每总结多一次,就加深了解多一点. cookie,一定是放在浏览器中的,用于浏览器保存一些小额度的内容.每次我们去访问 ...
- c#用webkit内核支持html5
[实例简介]经过测试可用 [实例截图] [核心代码] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 using System; ...
- bzoj4821
线段树 这题真是无聊 把式子拆开,然后可知维护xi,yi,xi^2,xi*yi,重点在于标记下传,当我们进行2号操作时,直接累加进答案和标记即可,进行3号操作时,update时先把自己这层赋值成要改变 ...
- JavaGraphics类的绘图方法
Graphics类提供基本绘图方法,Graphics类提供基本的几何图形绘制方法,主要有:画线段.画矩形.画圆.画带颜色的图形.画椭圆.画圆弧.画多边形.画字符串等. 1. 画线段:在窗口中画一条线段 ...
- E20170805-hm
mechanize vt. 使机械化; 用机械装置;
- Rails 服务器架设失败问题
更新: 2017/09/14 补充了简单的确认号码的方法 A server is already running. Check /Users/...../pids/server.pid. Exitin ...
- BZOJ 1129 exgcd+CRT+线段树
思路: 先copy一下百度百科 作为预备知识吧多重全排列定义:求r1个1,r2个2,…,rt个t的排列数,设r1+r2+…+rt=n,设此排列数称为多重全排列,表示为$P(n;r1,r2,…,rt)$ ...
- websocket的原理
首先明确几点: 1. websocket是一种协议.是html5的一种新协议: 2. 与http的区别是,它是一种双向通信协议,服务器和客户端都能主动向对方发送或接受数据: 3. websocket需 ...
- jQuery里$.post请求,后台返回结果为“json”格式,前台解析错误问题记录
在JSP页面使用$.post请求后台返回json数据时,在最后 必须加上返回数据格式为json的才行.不然JSP页面解析会出错.
- day02_12/12/2016_bean的实例化之静态工厂方式