文章目录

  • 前言
  • 操作
    • 合并
    • 分裂
    • 插入
    • 删除
    • 查找第k大
    • 查询x的排名
    • 前驱后继
  • 完整代码

所谓无旋treap,就是不带旋转的treap

前言

现在“理论上”我会四种平衡树了
之前说无旋treap功能弱,是我狗眼看银低了qwq
这玩意区间上该搞的也能搞
而且确实是非常的 好写!!
有点想把这个作为默认项了
呜呜呜朝三暮四肿么办呐

操作

关键是合并和分裂

合并

考虑合并u和v两棵子树
把优先级高的作为根
剩下的接着合并即可

il int merge(int u,int v){if(!u) return v;if(!v) return u;if(tr[u].key>tr[v].key){tr[u].rs=merge(tr[u].rs,v);pushup(u);return u;}else{tr[v].ls=merge(u,tr[v].ls);pushup(v);return v;}
}

分裂

给定一个val
<=val的归一棵,>=val的归另一棵
讨论一些根归谁
然后递归一下即可
如果要求前k个一棵是一个道理

il void split(int x,int v,int &L,int &R){if(!x){L=R=0;return;}if(tr[x].val<=v){L=x;split(tr[L].rs,v,tr[L].rs,R);pushup(L);}else{R=x;split(tr[R].ls,v,L,tr[R].ls);pushup(R);}return;
}

插入

插入一个为v的元素
把树按照v掰成两个
把开的新点merge上去即可

il void ins(int v){int a(0),b(0),c(0);split(r,v,a,b);c=New(v);r=merge(merge(a,c),b);return;
}

删除

删除一个v
先把<=v的split出来
再把<v的split出来
剩下的全是=v的
把其左右子树合并就相当于扣掉一个
最后merge回去就行

il void del(int v){int a(0),b(0),c(0);split(r,v,a,b);split(a,v-1,a,c);r=merge(merge(a,merge(tr[c].ls,tr[c].rs)),b);
}

查找第k大

BST常规操作

il int findnth(int kth){//printf("findnth:%d\n",kth);int x=r;while(1){//printf("x=%d val=%d siz=%d ls=%d rs=%d\n",x,tr[x].val,tr[x].siz,tr[x].ls,tr[x].rs);if(kth<=tr[tr[x].ls].siz) x=tr[x].ls;else if(kth==tr[tr[x].ls].siz+1) return tr[x].val;else{kth-=tr[tr[x].ls].siz+1;x=tr[x].rs;}}
}

查询x的排名

这个用常规的BST的操作是 不行 的!
因为树上存在这权值相同的点
但可以直接把<x的split出来查询siz
也很方便
最后记得要merge回去!

il int findrnk(int v){int a(0),b(0),c(0),res;split(r,v-1,a,b);res=tr[a].siz;r=merge(a,b);return res+1;
}

前驱后继

BST典中典了属于是

findnth(findrnk(x)-1)//前驱
findnth(findrnk(x+1))//后继

完整代码

当然是普通平衡树啦

#include<bits/stdc++.h>
#define ll long long
#define il inline
using namespace std;
const int N=1e6+100;
const int M=2e6+100;
ll read(){ll x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();};while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x*f;
}
int n,m,s,t;
struct node{int ls,rs,val,siz,key;
}tr[N<<2];
int r,tot;
il int New(int v){++tot;tr[tot].siz=1;tr[tot].ls=tr[tot].rs=0;tr[tot].key=rand();tr[tot].val=v;return tot;
}
il void pushup(int x){tr[x].siz=tr[tr[x].ls].siz+tr[tr[x].rs].siz+1;return;
}
il int merge(int u,int v){if(!u) return v;if(!v) return u;if(tr[u].key>tr[v].key){tr[u].rs=merge(tr[u].rs,v);pushup(u);return u;}else{tr[v].ls=merge(u,tr[v].ls);pushup(v);return v;}
}
il void split(int x,int v,int &L,int &R){if(!x){L=R=0;return;}if(tr[x].val<=v){L=x;split(tr[L].rs,v,tr[L].rs,R);pushup(L);}else{R=x;split(tr[R].ls,v,L,tr[R].ls);pushup(R);}return;
}
il int findnth(int kth){//printf("findnth:%d\n",kth);int x=r;while(1){//printf("x=%d val=%d siz=%d ls=%d rs=%d\n",x,tr[x].val,tr[x].siz,tr[x].ls,tr[x].rs);if(kth<=tr[tr[x].ls].siz) x=tr[x].ls;else if(kth==tr[tr[x].ls].siz+1) return tr[x].val;else{kth-=tr[tr[x].ls].siz+1;x=tr[x].rs;}}
}
il int findrnk(int v){int a(0),b(0),c(0),res;split(r,v-1,a,b);res=tr[a].siz;r=merge(a,b);return res+1;
}
il void ins(int v){int a(0),b(0),c(0);split(r,v,a,b);c=New(v);r=merge(merge(a,c),b);return;
}
il void del(int v){int a(0),b(0),c(0);split(r,v,a,b);split(a,v-1,a,c);r=merge(merge(a,merge(tr[c].ls,tr[c].rs)),b);
}
int main(){n=read();for(int i=1;i<=n;i++){int op=read(),x=read();switch(op){case 1:{ins(x);break;}case 2:{del(x);break;}case 3:{printf("%d\n",findrnk(x));break;}case 4:{printf("%d\n",findnth(x));break;}case 5:{printf("%d\n",findnth(findrnk(x)-1));break;}case 6:{printf("%d\n",findnth(findrnk(x+1)));break;}}}return 0;
}
/*
*/

thanks for reading!

模板:无旋treap相关推荐

  1. 无旋treap的简单思想以及模板

    因为学了treap,不想弃坑去学splay,终于理解了无旋treap... 好像普通treap没卵用...(再次大雾) 简单说一下思想免得以后忘记.普通treap因为带旋转操作似乎没卵用,而无旋tre ...

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

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

  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. 无旋treap 文艺平衡树

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

  6. 无旋Treap(fhq)

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

  7. [BZOJ1503][NOI2004]郁闷的出纳员 无旋Treap

    1503: [NOI2004]郁闷的出纳员 Time Limit: 5 Sec  Memory Limit: 64 MB Description OIER公司是一家大型专业化软件公司,有着数以万计的员 ...

  8. luogu P3850 [TJOI2007]书架(平衡树、无旋treap(按排名分裂))

    luogu P3850 [TJOI2007]书架 这里要的是字符串,所以我们最好用一个map映射一下,不要在结构体中用string代替val. fhq-treap中所有的排名实际上都指的是前面有多少个 ...

  9. P2596 [ZJOI2006]书架 无旋treap 按照排名分裂

    传送门 文章目录 题意: 思路: 题意: 实现如下操作: 思路: fhq-treap板子辣,不要被他的编号误导了,我们还是需要按照排名来分裂,从上到下标号1−n1-n1−n即可,注意在按照排名分裂的时 ...

最新文章

  1. 《深入理解计算机系统》学习心得二:关于show-bytes的 学习
  2. Unix的标准I/O与重定向的若干概念解析
  3. BigData预处理(完整步骤)
  4. python3反转列表的三种方式
  5. extend 对象继承
  6. STM32那点事(5)_ADC(中)
  7. Docker和Kubernetes应用程序打包:Metaparticle、Pulumi与Ballerina比较
  8. 智慧农业、数字农业、农产品交易、发布供应、采购详情、报价列表、交易订单、供应大厅、采购大厅、发布采购、采购需求、采购订单、在售商品、出售订单、账户中心、洽谈列表、入驻申请、Axure原型、农业数据看板
  9. Python中循环(列表循环)的学习笔记~
  10. ibm服务器安装ghostxp系统,IBM ThinkPad X61s安装WIN XP系统
  11. 破解大众点评字体反爬
  12. 面对众多客户/用户需求,每个都紧急,怎么排期?
  13. 优盘在计算机上无法显示,U盘在电脑上不显示的原因
  14. spyder python调试_Spyder如何调试
  15. 人人都是产品经理(善用用户反馈——浅谈用户反馈数据的处理)
  16. 不要随便借出你的帐号
  17. SVG动画和CSS转换:复杂的爱情故事
  18. 作为一个新人,怎样学习嵌入式Linux ?(韦东山)
  19. Spring使用WebSocket、SockJS、STOMP实现消息功能
  20. 关于三星SSD的固态优化

热门文章

  1. redis 查询缓存_Redis缓存总结:淘汰机制、缓存雪崩、数据不一致....
  2. python基金会主席入门教程_Python基金会-文件IO操作,python,基础
  3. 输出毫秒_自学单片机第十三篇上:单点输出
  4. android vcard解析代码,Android使用vcard文件的方法简单实例
  5. mysql 卸载插件_MySQL 插件安装或卸载(window validate_password 为例)
  6. 加个ing是什么意思_take的意思竟然是“要求”?奇奇怪怪的熟词僻义打卡终于来了!...
  7. gather torch_浅谈Pytorch中的torch.gather函数的含义
  8. python新闻评论分析_从新闻文章中提取评论
  9. linux gcc出错,编译arm-linux-gcc出错
  10. 高度平衡的二叉搜索树基础概念与经典题目(Leetcode题解-Python语言)