Treap-普通平衡树
来源:互联网 发布:2017吉大网络教育收费 编辑:程序博客网 时间:2024/04/27 20:34
https://www.luogu.org/problem/show?pid=3369
最近学习了treap,找了道题目做做 全抄hz...
因为普通的二叉树,会退化成链;
所以你把读入打乱顺序再构造二叉树,就明显卡不掉;
平平均深度logn;
treap就是这样的;
在插入一个数时,我们搞一个rnd,赋值随机;
然后如果当前的这个节点rnd小于其父节点,那么就把他转到父节点的位置;
这样好比是给这个节点一个随机的顺序;
那么即使毒瘤出题人把一开始数据的顺序搞特殊,故意要卡你,因为每个数据有了这么一个随机位置,相当于把读入打乱啦,所以卡不掉;
要是被卡了是RP问题;
http://baike.baidu.com/link?url=VNd3Gm-SrYJpjVllSPRvnjBV5MwdxH8wnwUY5HNp3agTInLjpte8a0a_pGerSz3u2yysC76xy9zzntbYX1GfMq
百度百科;
我们浅谈关于转;
这里我们要把3节点转到上面来;
我们发现转好之后几个数字的再二叉树里的大小关习是不变的;
这就是我们转的原理;
可以看出2-1|||||||||3-5这两条边是不变的;
自己感受感受;
其实转就是怎么个过程,换了种方式存储信息;
但转就把3节点向上移动了;
代码
#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>using namespace std;struct treap{ int l,r,v,size,w,rnd;//size是包括根节点,这个子树的节点总数,w是这个v值出现了几次,所以treap里面每个值只有一个; }tr[100005];int m,x,y,z,root,size;//root是根节点,根节点不一定是1,因为会转掉的;size就个计数 void now(int k){tr[k].size=tr[tr[k].l].size+tr[tr[k].r].size+tr[k].w;}//更新size void lturn(int &k){//这个过程建议大家直接好好模拟,思考; int t=tr[k].r; tr[k].r=tr[t].l; tr[t].l=k; tr[t].size=tr[k].size; now(k); k=t;}void rturn(int &k){ int t=tr[k].l; tr[k].l=tr[t].r; tr[t].r=k; tr[t].size=tr[k].size; now(k); k=t;}void insert(int &k,int x){ if(!k){ k=++size; tr[k].size=tr[k].w=1; tr[k].v=x; tr[k].rnd=rand();//我们只需要一组随机数,所以不用种子; return; } tr[k].size++; if(tr[k].v==x){tr[k].w++;return;}//如果已经出现过直接加再w上 if(tr[k].v<x){ insert(tr[k].r,x);//先找到叶节点的位置,再不断旋转上升; if(tr[tr[k].r].rnd<tr[k].rnd)lturn(k);//左节点右旋; }else{ insert(tr[k].l,x); if(tr[tr[k].l].rnd<tr[k].rnd)rturn(k); } }void del(int &k,int x){ if(!k)return; if(tr[k].v==x){ if(tr[k].w>1){tr[k].size--;tr[k].w--;return;}//如果有多个那删一个 if(tr[k].l*tr[k].r==0){k=tr[k].l+tr[k].r;return;}//这个是有一个节点和无节点的情况 int l=tr[k].l,r=tr[k].r; if(tr[l].rnd<tr[r].rnd)rturn(k);else lturn(k);//把x转到下一层,直到转到叶子节点 del(k,x); return; } tr[k].size--; if(tr[k].v<x)del(tr[k].r,x);else del(tr[k].l,x);//先找到位置 }int Rank(int k,int x){ if(!k)return 0; if(tr[k].v==x)return tr[tr[k].l].size+1; if(tr[k].v>x)return Rank(tr[k].l,x); return tr[tr[k].l].size+tr[k].w+Rank(tr[k].r,x);}int num(int k,int x){ if(!k)return 0; if(x<=tr[tr[k].l].size)return num(tr[k].l,x); if(x>tr[tr[k].l].size+tr[k].w)return num(tr[k].r,x-tr[tr[k].l].size-tr[k].w); return tr[k].v;}int pro(int k,int x){//推荐大家用hzwer的写法,这个写法比较乱 if(!k)return 0; if(tr[k].v>=x)return pro(tr[k].l,x); int ans=pro(tr[k].r,x); if(ans)return ans;else return tr[k].v;}int sub(int k,int x){ if(!k)return 0; if(tr[k].v<=x)return sub(tr[k].r,x); int ans=sub(tr[k].l,x); if(ans)return ans;else return tr[k].v;}int main(){ scanf("%d",&m); while(m--){ scanf("%d%d",&y,&x); if(y==1)insert(root,x);else if(y==2)del(root,x);else if(y==3)printf("%d\n",Rank(root,x));else if(y==4)printf("%d\n",num(root,x));else if(y==5)printf("%d\n",pro(root,x));else if(y==6)printf("%d\n",sub(root,x)); }}
1 2
- 普通平衡树 treap
- Treap-普通平衡树
- treap 普通平衡树
- 【Treap】[CQBZOJ2803]普通平衡树
- treap普通平衡树bzoj3224
- 【模板】普通平衡树 Treap
- [BZOJ3224]Tyvj 1728 普通平衡树 && treap
- 【Treap】【TYVJ 1728】普通平衡树
- bzoj3224 普通平衡树【treap版】
- 洛谷P3369 普通平衡树(Treap/Splay)
- bzoj3224 Tyvj 1728 普通平衡树 treap
- 【treap模板】【TyvJ 1728】【普通平衡树】
- 【Treap/非旋转Treap】BZOJ3224 [Tyvj1728]普通平衡树
- 3224: Tyvj 1728 普通平衡树 P3369 【模板】普通平衡树(Treap/SBT)Treap
- BZOJ3224 普通平衡树(Treap实现名次树)
- 【模板】【Treap/SBT】【树堆】普通平衡树【洛谷P3369】
- 【treap】【bzoj 3224】: Tyvj 1728 普通平衡树
- BZOJ 3224 普通平衡树 裸treap模板题
- bzoj 4327: JSOI2012 玄武密码 (AC自动机)
- leecode 解题总结:365. Water and Jug Problem
- 关于python的bottle框架跨域请求报错问题的处理
- L1-007. 念数字
- CRF L-BFGS Line Search原理及代码分析
- Treap-普通平衡树
- Android 如何通知用户更新app的版本
- The Bhattacharyya coefficient
- kafka Consumer均衡算法,partition的个数和消费组组员个数的关系
- 面试思考
- 使用dom4j对xml文件进行读取和输出操作
- 64位
- java虚拟机内存区域的划分以及作用详解
- gym 101124 Problem E. Dance Party(概率)