关于非旋转treap的学习
非旋转treap的操作基于split和merge操作,其余操作和普通平衡树一样,复杂度保证方式与旋转treap差不多,都是基于一个随机的参数,这样构出的树树高为\(logn\)
split
作用:将原平衡树分为排名为\([1,k]\),\([k+1,n]\)的两棵平衡树
实现:
1.如果\(x\)左儿子的子树大小\(size[l]==k\),那么\(x\)左儿子即为\([1,k]\)这个平衡树的根,\(x\)本身为另一颗平衡树的根
2.如果\(x\)左儿子的子树大小\(size[l]+1==k\),那么\(x\)为\([1,k]\)这个平衡树的根,\(x\)右儿子为另一颗平衡树的根
3.如果是上述情况,直接把左儿子或右儿子接上去就好
4.否则,递归处理,直到出现这两种情况位置
inline void split(int x,int k,int &a,int &b){
if(!k){a=0;b=x;return ;}
int l=ch[x][0],r=ch[x][1];
if(sz[l]==k)ch[x][0]=0,a=l,b=x;
else if(sz[l]+1==k)ch[x][1]=0,a=x,b=r;
else if(sz[l]>k)split(l,k,a,ch[x][0]),b=x;
else split(r,k-sz[l]-1,ch[x][1],b),a=x;
upd(x);
}
merge
作用:将两棵平衡树合并,合并后参数满足\(heap\)的性质,且满足平衡树性质.
实现:
我们强制\(merge(x,y)\)中\(x\)的所有节点的关键字都小于所有\(y\)的关键字,根据关键字合并即可.
inline int merge(int x,int y){
if(!x||!y)return x+y;
if(key[x]>key[y]){
ch[x][1]=merge(ch[x][1],y);
upd(x);
return x;
}
else{
ch[y][0]=merge(x,ch[y][0]);
upd(y);
return y;
}
}
insert
以\(x\)的前驱为界,拆原树为两棵树,将左树合并到\(x\),再将\(x\)合并到右树
inline void ins(int x){
v[++cnt]=x;key[cnt]=rand();sz[cnt]=1;
int l,r;
split(rt,rank(x)-1,l,r);
rt=merge(merge(l,cnt),r);
}
delet
以\(x\)为界\(split\)原树,删除\(x\)后再合并左右子树
inline void Delet(int x){
int l,r;
split(rt,x,l,r);
split(l,x-1,l,x);
rt=merge(l,r);
}
标记下放
只需在\(merge\),\(split\),\(kth\),\(rank\)函数前下放即可
完整代码:
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const int N=100005;
int ch[N][2],sz[N],key[N],cnt=0,v[N],rt;
inline void upd(int x){sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1;}
inline void split(int x,int k,int &a,int &b){
if(!k){a=0;b=x;return ;}
int l=ch[x][0],r=ch[x][1];
if(sz[l]==k)ch[x][0]=0,a=l,b=x;
else if(sz[l]+1==k)ch[x][1]=0,a=x,b=r;
else if(sz[l]>k)split(l,k,a,ch[x][0]),b=x;
else split(r,k-sz[l]-1,ch[x][1],b),a=x;
upd(x);
}
inline int merge(int x,int y){
if(!x||!y)return x+y;
if(key[x]>key[y]){
ch[x][1]=merge(ch[x][1],y);
upd(x);
return x;
}
else{
ch[y][0]=merge(x,ch[y][0]);
upd(y);
return y;
}
}
inline int rank(int k){
int x=rt,ret=1;
while(x){
if(k<=v[x])x=ch[x][0];
else ret+=sz[ch[x][0]]+1,x=ch[x][1];
}
return ret;
}
inline int kth(int k){
int x=rt,sum;
while(x){
sum=sz[ch[x][0]];
if(sum==k-1)return v[x];
if(sum>=k)x=ch[x][0];
else x=ch[x][1],k-=sum+1;
}return 0;
}
inline void ins(int x){
v[++cnt]=x;key[cnt]=rand();sz[cnt]=1;
int l,r;
split(rt,rank(x)-1,l,r);
rt=merge(merge(l,cnt),r);
}
inline void Delet(int x){
int l,r;
split(rt,x,l,r);
split(l,x-1,l,x);
rt=merge(l,r);
}
void work()
{
int n,op,x;
scanf("%d",&n);
while(n--){
scanf("%d%d",&op,&x);
if(op==1)ins(x);
else if(op==2)Delet(rank(x));
else if(op==3)printf("%d\n",rank(x));
else if(op==4)printf("%d\n",kth(x));
else if(op==5)printf("%d\n",kth(rank(x)-1));
else if(op==6)printf("%d\n",kth(rank(x+1)));
}
}
int main()
{
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
work();
return 0;
}
关于非旋转treap的学习的更多相关文章
- 左偏树 / 非旋转treap学习笔记
背景 非旋转treap真的好久没有用过了... 左偏树由于之前学的时候没有写学习笔记, 学得也并不牢固. 所以打算写这么一篇学习笔记, 讲讲左偏树和非旋转treap. 左偏树 定义 左偏树(Lefti ...
- [NOIP]2017列队——旋转treap/非旋转treap
Sylvia 是一个热爱学习的女孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia所在的方阵中有n × m名学生,方阵的行数为 n,列数为m. 为了便 ...
- 平衡树及笛卡尔树讲解(旋转treap,非旋转treap,splay,替罪羊树及可持久化)
在刷了许多道平衡树的题之后,对平衡树有了较为深入的理解,在这里和大家分享一下,希望对大家学习平衡树能有帮助. 平衡树有好多种,比如treap,splay,红黑树,STL中的set.在这里只介绍几种常用 ...
- [bzoj3173]最长上升子序列_非旋转Treap
最长上升子序列 bzoj-3173 题目大意:有1-n,n个数,第i次操作是将i加入到原有序列中制定的位置,后查询当前序列中最长上升子序列长度. 注释:1<=n<=10,000,开始序列为 ...
- [Codeforces702F]T-Shirts——非旋转treap+贪心
题目链接: Codeforces702F 题目大意:有$n$种T恤,每种有一个价格$c_{i}$和品质$q_{i}$且每种数量无限.现在有$m$个人,第$i$个人有$v_{i}$元,每人每次会买他能买 ...
- BZOJ5063旅游——非旋转treap
题目描述 小奇成功打开了大科学家的电脑. 大科学家打算前往n处景点旅游,他用一个序列来维护它们之间的顺序.初 始时,序列为1,2,...,n. 接着,大科学家进行m次操作来打乱顺序.每次操作有6步: ...
- BZOJ3223文艺平衡树——非旋转treap
此为平衡树系列第二道:文艺平衡树您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作: 翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 ...
- BZOJ3224普通平衡树——非旋转treap
题目: 此为平衡树系列第一道:普通平衡树您需要写一种数据结构,来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数, ...
- BZOJ3729Gty的游戏——阶梯博弈+巴什博弈+非旋转treap(平衡树动态维护dfs序)
题目描述 某一天gty在与他的妹子玩游戏.妹子提出一个游戏,给定一棵有根树,每个节点有一些石子,每次可以将不多于L的石子移动到父节点,询问将某个节点的子树中的石子移动到这个节点先手是否有必胜策略.gt ...
随机推荐
- c++第0次作业
1.你认为大学的学习生活.同学关系.师生应该是怎样? 随着大学生活的慢慢到来,我开始领悟到大学并不是自由的天堂,相反,我们更加的走进社会这个牢笼.在这个牢笼中有着从前的我们并不需要在意和考虑的规则与问 ...
- continue和break的特殊用法。
break在程序中一般来说的作用就是跳出当前循环,然后再据需执行循环外的语句.continue也是对当前循环来说直接进入到下一次循环.其实我们在程序中有时候循环体嵌套太多,进行到某一步是希望直接bre ...
- 《高级软件测试》云平台Jira的配置
首先点击进入以下网址: https://www.atlassian.com/ondemand/signup/form?product=jira-software.ondemand 填写好信息,Star ...
- JVM笔记7-内存分配与回收策略
1.对象优先在Eden分配 大多数情况下,对象在新生代Eden区中分配.当Eden区中没有足够空间分配时,虚拟机将发起一次Minor GC.虚拟机提供了-XX:PrintGCDetails 这个收集器 ...
- 解决vue2.0路由 TypeError: Cannot read property 'matched' of undefined 的错误问题
刚开始使用vue-router2.0,虽然也用了vux,用起来却发现一个问题--具体如下: 正常情况下使用脚手架跑完之后,然后修改源项目,首先在main.js入口里把该import进去的vuex,vu ...
- 集合Collection总览
前言 声明,本文使用的是JDK1.8 从今天开始正式去学习Java基础中最重要的东西--->集合 无论在开发中,在面试中这个知识点都是非常非常重要的,因此,我在此花费的时间也是很多,得参阅挺多的 ...
- CRC 校验
匠心零度 转载请注明原创出处,谢谢! 说明 上篇RocketMQ(二):RPC通讯介绍了rocketmq的一些rpc细节,其实这些内容不仅仅是rocketmq内容,任何通信模块基本都是类似的,这块内容 ...
- 2018年Web前端自学路线
本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. Web前端入门的自学路线 新手入门前端,需要学习的基础内容有很多,如下. ...
- Linux将端口设置进防火墙的白名单
1.先检查linux服务器的端口是否被防火墙拦住 `telnet 172.168.1.101 8080后面跟端口号,如果连接上证明是防火墙白名单.如果没有配置 vi /etc/sysconfig/ip ...
- (数字IC)低功耗设计入门(八)——物理级低功耗设计&to be continued?
前面学习了从系统级到门级的低功耗设计,现在简单地了解了一下物理级设计.由于物理级的低功耗设计与后端有关了,这里就不详细学习了.这里主要是学习了一些基本原则,在物理级,进行低功耗设计的基本原则是: ...