Treap学习小计
来源:互联网 发布:破解手机收费软件 编辑:程序博客网 时间:2024/05/18 01:36
啊啊啊啊,终于学会打treap了啊啊啊啊啊
一个小故事
从前,Tree和Heap相遇了,他们相爱了,于是生下了一个孩子,他叫什么呢?于是他姓Tr名字叫eap,所以他就叫Treap(啦啦啦啦啦啦啦)
Treap的性质
既然他爸是Tree,他妈是Heap,那必定会遗传他爸和他妈的血统啊。
所以他是棵Balanced Binary Tree,同时从其每个点的键值来看,他的形态又是一棵不严格的Heap,当然由于这是从他妈那遗传的,所以他仅仅满足了Heap中:一个点的键值小于(或大于)他的两个儿子的键值。
插入
对于一个点的插入,我们像普通的二叉搜索树一样找到相应位置然后插入,注意我们要维护其heap的形态,所以我们要将新插入的点到根节点的路径类似普通的Heap的方法一样向上,但是由于这是棵二叉搜索树,于是我们要用旋转而非交换。
删除
删除一个节点,若其只有一个儿子或没有儿子,那么其直接用其儿子代替它或直接删掉,若它有两个儿子,那么看它的左右儿子那个键值小,若左儿子小则右旋,右儿子小则左旋,然后继续删除。
其它操作
由于其它操作与普通平衡树基本一样,我就不说了哈。
code(向hzw学习了呀)
#include<cstring>#include<cstdio>#include<algorithm>#include<cmath>#include<iostream>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;typedef long long LL;typedef double db;int get(){ char ch; int s=0; bool pd=0; while(ch=getchar(),(ch<'0'||ch>'9')&&ch!='-'); if (ch=='-')pd=1; else s=ch-'0'; while(ch=getchar(),ch>='0'&&ch<='9')s=s*10+ch-'0'; if (pd)return -s; return s;}const int N = 100010;struct point{ int l,r,tot,v,key,w;}tree[N];int tot,n,root;void updata(int x){ tree[x].tot=tree[tree[x].l].tot+tree[tree[x].r].tot+tree[x].w;}void rturn(int &x){ int y=tree[x].l;tree[x].l=tree[y].r;tree[y].r=x; tree[y].tot=tree[x].tot;updata(x);x=y;}void lturn(int &x){ int y=tree[x].r;tree[x].r=tree[y].l;tree[y].l=x; tree[y].tot=tree[x].tot;updata(x);x=y;}void insert(int &now,int x){ if (!now){ tree[now=++tot].v=x; tree[now].key=rand(); tree[now].tot=tree[now].w=1; return; } tree[now].tot++; if (x==tree[now].v)tree[now].w++; else if (x<tree[now].v){ insert(tree[now].l,x); if (tree[tree[now].l].key<tree[now].key)rturn(now); } else{ insert(tree[now].r,x); if (tree[tree[now].r].key<tree[now].key)lturn(now); }}void del(int &now,int x){ if (tree[now].v==x){ if (tree[now].w>1){ tree[now].w--; tree[now].tot--; return; } if (tree[now].l*tree[now].r==0)now=tree[now].l+tree[now].r; else{ if (tree[tree[now].l].key<tree[tree[now].r].key)rturn(now),del(now,x); else lturn(now),del(now,x); } return; } tree[now].tot--; if (tree[now].v>x)del(tree[now].l,x); else del(tree[now].r,x);}int rank(int now,int x){ if (!now)return -N; if (tree[now].v==x)return tree[tree[now].l].tot+1; if (x<tree[now].v)return rank(tree[now].l,x); return tree[tree[now].l].tot+tree[now].w+rank(tree[now].r,x);}int kth(int now,int k){ if (!now)return 0; if (tree[tree[now].l].tot<k&&k<=tree[tree[now].l].tot+tree[now].w) return now; if (k<=tree[tree[now].l].tot)return kth(tree[now].l,k); return kth(tree[now].r,k-tree[tree[now].l].tot-tree[now].w);}int pre(int now,int x){ if (!now)return 0; if (tree[now].v<x){ int v=pre(tree[now].r,x); if (v)return v; return now; } return pre(tree[now].l,x);}int suf(int now,int x){ if (!now)return 0; if (tree[now].v>x){ int v=suf(tree[now].l,x); if (v)return v; return now; } return suf(tree[now].r,x);}int main(){ n=get(); srand(57789); int tim=0; fo(i,1,n){ int w,opt=get(),x=get(); switch(opt){ case 1:insert(root,x);break; case 2:del(root,x);break; case 3:printf("%d\n",rank(root,x));break; case 4:w=kth(root,x);printf("%d\n",tree[w].v);break; case 5:w=pre(root,x);printf("%d\n",tree[w].v);break; case 6:w=suf(root,x);printf("%d\n",tree[w].v);break; } } return 0;}
建议学习新的平衡树可以用【bzoj3224】Tyvj 1728 普通平衡树 这题啊
0 0
- Treap学习小计
- 学习小计
- 学习小计
- Java学习小计
- iOS学习小计划
- eXosip 学习小计
- or1200学习小计划
- gnuplot 学习小计4
- extjs学习小计
- ucos学习小计
- android学习Fragment小计
- 指针学习小计
- ztree学习小计
- linux 学习小计
- 杜教筛学习小计
- c++ STL 学习小计
- 学习笔记 Treap
- 朴素treap学习
- hdu 3658 HDU 3658 How many words(矩阵快速幂)
- 【数字图像处理学习笔记之五】形态学开闭运算
- adb 命令
- Android Studio 问题解决记录
- linux学习日记(二)
- Treap学习小计
- Java NIO 学习(三)--FileChannel
- 5、最长公共子序列
- adb shell 获取版本信息
- 【那些年遇到过的面试题】malloc 原理
- Nginx数据结构——ngx_queue_t
- Java关系运算
- 这是我第一条博客
- 替换空格(c语言完整版程序)