参考视频:https://www.bilibili.com/video/BV1ft411E7JW?t=1780
代码中有较为详细的注释

#include <bits/stdc++.h>
using namespace std;int cnt,root;
mt19937 rnd(233);  //随机数
struct Node{int l,r,val,key,size;
}fhq[100010];
int newnode(int val){  //开辟新结点fhq[++cnt].val=val;fhq[cnt].key=rnd();fhq[cnt].size=1;return cnt;   //直接返回一个新结点
}void update(int now){  //push_up更新节点大小(当加入了新结点)fhq[now].size=fhq[fhq[now].l].size+fhq[fhq[now].r].size+1;
}
void spilt(int now,int val,int &x,int &y){ //分裂乘两棵树if(!now) x=y=0;  //如果是一颗空树,直接返回x,y是空树即可else{if(fhq[now].val<=val){  //这里是按值分裂把小于等于val值得分到x树,大于val得分到y树x=now; //这个值左孩子上得所有结点都属于x这棵树spilt(fhq[now].r,val,fhq[now].r,y);//右孩子上大部分都会大于这个值,//也有可能会有小于val这个值得,所以我们要继续递归右子树进行查找}else{y=now;   //复读机spilt(fhq[now].l,val,x,fhq[now].l);}update(now);}
}
int merge(int x,int y){   //把两棵树合并起来if(!x||!y) return x+y;if(fhq[x].key>fhq[y].key){   //既要符合堆得性质,又要符合搜索树得性质//我们知道x这棵树上得值全都小于y这颗树上得值,// 所以当x得key大于y这个key得时候,y在x得右下方(既要在右边,也要在下面)//所以让x得右子树跟y合并fhq[x].r=merge(fhq[x].r,y);update(x);return x;}else{fhq[y].l=merge(x,fhq[y].l);update(y);return y;}
}
int x,y,z;
void insert(int val){  //插入某值spilt(root,val,x,y);  //先把树按照val值分裂开//因为x树都小于等于val,所以我们直接让新结点跟x合并起来//再把x树跟y树合并起来root=merge(merge(x,newnode(val)),y);
}
void del(int val){ //删除(此del不可以删除树上没有得值)//先按照val将树分裂开//再把x树按照val-1分裂成x,y树//那么y树上所有得值都等于valspilt(root,val,x,z);spilt(x,val-1,x,y);//直接把y得根节点去掉即可,也就是把左右子树合并y=merge(fhq[y].l,fhq[y].r);root=merge(merge(x,y),z);//最后把他们合并起来即可
}
int get_rank(int val){  //排名spilt(root,val-1,x,y);//按照val-1把树分为xy,那么x上树所有值都小于val//那么x树上得根节点得size即为比他小得数得个数,再+1即可int temp=fhq[x].size+1;root=merge(x,y); //不要忘记把树还原//cout<<fhq[x].size<<endl;return temp;}
int get_num(int rank){int now=root;while (now){  if(fhq[fhq[now].l].size+1==rank) break;  //如果找到直接返回结点值//如果搜索过得数大于rank,那么我们要往左数搜索//因为右子树的值已经大于rank了,所以答案一定不在右子树上else if(fhq[fhq[now].l].size>=rank) now=fhq[now].l;//及时减去已经走过的排名,类似于主席树第k大思想else{rank-=fhq[fhq[now].l].size+1;now=fhq[now].r;}}return fhq[now].val;
};int pre(int val){   //找前驱,按照val-1分裂此树//在他前面的哪个数,一定是在x树上的最右端(最大值)spilt(root,val-1,x,y);int now=x;while (fhq[now].r) now=fhq[now].r;int temp=fhq[now].val;root=merge(x,y);return temp;
}
int nxt(int val){//找后继,按照val分裂此树//在他后面的树一定是y树上最左边的值(最小值)spilt(root,val,x,y);int now=y;while (fhq[now].l) now=fhq[now].l;int temp=fhq[now].val;root=merge(x,y);return temp;
}void check(int now){  //中序遍历if(!now) return;check(fhq[now].l);printf("%d ",fhq[now].val);check(fhq[now].r);
}
int main() {int n;cin>>n;while (n--){int opt,x;scanf("%d%d",&opt,&x);if(opt==1) insert(x);if(opt==2) del(x);if(opt==3) printf("%d\n",get_rank(x));if(opt==4) printf("%d\n",get_num(x));if(opt==5) printf("%d\n",pre(x));if(opt==6) printf("%d\n",nxt(x));
//        check(root);
//        cout<<endl;}return 0;
}

平衡二叉树-FHQ Treap(无旋平衡树)c/c++代码实现相关推荐

  1. 模板 - FHQ - treap 无旋平衡树

    整理的算法模板合集: ACM模板 目录 FQH - treap 无旋平衡树 按权值分裂 按排名分裂 文艺平衡树 可持久化序列 FQH - treap 无旋平衡树 operator 1 : 插入一个数 ...

  2. 【模板】FHQ Treap

    FHQ Treap 无旋Treap 维护的信息 c h [ i ] [ 0 / 1 ] ch[i][0/1] ch[i][0/1] v a l [ i ] val[i] val[i] f i x [ ...

  3. luogu P2596 [ZJOI2006]书架(平衡树、无旋treap(按排名分裂)一些更复杂的操作)

    P2596 [ZJOI2006]书架 无旋treap可以维护一棵树的中序遍历结果.但是不支持通过编号来找节点.于是在无旋treap的基础上,我维护了每个节点的父亲,这样就可以求出一个节点是中序遍历中的 ...

  4. BST、AVL、BTree、B+Tree、B*Tree、23Tree、234Tree、TTree、RBTree、LLRBTree、AATree、SplayTree、Treap、无旋Treap、scap

    喜欢这篇文章吗?喜欢的话去看博主的置顶博客,即可依据分类找到此文章的原版得到更好的体验, 图片及代码显示的问题,笔者深感抱歉,想要更好的体验去原博文即可. title: tree mathjax: t ...

  5. 平衡树学习笔记之 fhq Treap

    平衡树学习笔记 1:fhq Treap(非旋 Treap) 正文开始前首先 %%% fhq 大佬. 众所周知,平衡树是一种 非常猥琐 码量堪忧的数据结构. 他的祖先是一种叫做二叉搜索树 ( B S T ...

  6. 浅尝无旋Treap (基于洛谷P3391 文艺平衡树)

    说是浅尝吧,确实也挺浅的,完全是基于下面这道题写的↓ 洛谷P3391 自己去看题,我是懒得粘了... 分析 其实也没有什么好分析的,这就是一道Splay树的模板题,解决一般的Treap不能解决的区间维 ...

  7. 无旋Treap(fhq)

    一.Treap的性质 Treap就是集BST.Heap二者的性质于一身,即能够支持BST的操作,有能够保证Heap的深度.但BST和Heap的性质似乎有些矛盾,前者是左子树<根<右子树,后 ...

  8. 【FHQ treap】维护书架(金牌导航 无旋式treap-1)

    维护书架 金牌导航 无旋式treap-1 题目大意 给出一个序列a,编号为1~n,让你做若干操作,操作有五种: 1.把第x个数放在最前面 2.把第x个数放在最后面 3.把第x个数和第x±1x\pm 1 ...

  9. 无旋treap 文艺平衡树

    因为需要用到区间修改,所以该用splay(尚未填坑)或者无旋treap(刚刚填上) 最开始的建树用到了建笛卡尔树的方法,把id大于当前点的点不断出栈,又因为这道题的点是按序入栈的,所以当它无法让更多点 ...

最新文章

  1. python local global_python global与nonlocal关键字
  2. 【深度学习入门到精通系列】Recurrent和Residual解释
  3. slf4j、jcl、jul、log4j1、log4j2、logback大总结
  4. OpenCV为轮廓创建边界旋转框和椭圆
  5. Coding Contest HDU - 5988
  6. java当前4中引用_Java的四种引用
  7. Hinton神经网络公开课10 Combining multiple neural networks to improve generalization
  8. 前端公共reset.css模板
  9. window.parent,top,window.self,parent,opener
  10. MP(Multi-Link PPP)原理和实验
  11. 【夯实基础】Spring在ssh中的作用
  12. 标准评分卡分数计算原理_学习评分卡Gini指标?这篇看完就够了!
  13. 企业级大数据智能分析平台 -- DataA
  14. 自我觉察日志——9.17 (为什么老想买东西?)
  15. 刘汉国老师的3路单火智能开关
  16. 武汉科技大学计算机学院研究生复试,2019年武汉科技大学硕士研究生复试及录取工作方案...
  17. SQL数据库无法附加
  18. 2022-2028全球及中国光伏金属化铝膏行业研究及十四五规划分析报告
  19. 深信服售前产品经理面试准备材料(更新ing)
  20. 微软云计算官方中文网站上线啦

热门文章

  1. 网络工程师_域名知识点
  2. 台式计算机,笔记本电脑如何查看自己的电池损耗情况!
  3. 图像超分辨率网络:RCAN
  4. 30万字,“保姆级”可视化视觉设计优质学习攻略推荐
  5. 8个计算机视觉深度学习中常见的Bug
  6. python10-宝可梦数据分析-平民最强宝可梦系列(从0-1数据分析实战)
  7. python03-异常处理
  8. 栈与队列5——汉诺塔问题(方案二)
  9. Python logging调用Logger.info方法的处理过程
  10. php的PDO手记1