初探treap1
初探treap, 走入平衡树大家族.
平衡树大家族可还行.
参考资料
https://www.cnblogs.com/guoshaoyang/p/11300886.html
https://blog.csdn.net/yandaoqiusheng/article/details/85037548
https://blog.csdn.net/chenxiaoran666/article/details/81391565
普通平衡树
我的代码
基本上是上述一个参考资料简单修改了一点点,以及加上了很多注释.
/*
编号 题目 状态 分数 总时间 内存 代码 / 答案文件 提交者 提交时间
#919994 #104. 普通平衡树 Accepted 100 445 ms 1284 K C++ 11 / 2.6 K robot 2020-08-28 8:48:23
*/
#include <bits/stdc++.h>
using namespace std;
#define inc(i,a,b) for(int i=a;i<=b;i++)
#define dec(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
#define mst(a,b) memset(a,b,sizeof a)
#define pb push_back
inline int read(){
char ch=getchar();int f=1,x=0;
while(!isdigit(ch)) { if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){ x=x*10+ch-'0';ch=getchar();}
return f*x;
}
const int N=1e5+10;
int siz[N],key[N],cnt[N],rd[N],son[N][2];
int sz,rt;
// 要根据具体题目数据范围调整
const int INF=1e9+7;
// 用自带的rand 在洛谷上ac了
// 用这个手写的rand 有一个数据TLE了
/*
unsigned int seed;
int rand(){
return seed=(int) seed * 482711LL % 2147483647;
}
*/
inline void pushup(int x){
siz[x]=siz[son[x][0]]+siz[son[x][1]]+cnt[x];
}
inline void rotate(int &x,int y){
int o=son[x][y^1];
son[x][y^1]=son[o][y];
son[o][y]=x;
pushup(x);
pushup(o);
x=o;
}
void insert(int &p,int x){
if(!p){ p=++sz; siz[p]=cnt[p]=1; key[p]=x; rd[p]=rand(); return; }
if(key[p]==x){ cnt[p]++; siz[p]++; return; }
int d=(x>key[p]);
insert(son[p][d],x);
if(rd[p]<rd[son[p][d]]) rotate(p,d^1);
pushup(p);
}
void delet(int &p,int x){
if(!p) return;
if(x!=key[p]) delet(son[p][x>key[p]],x);
else{
if(!son[p][0]&&!son[p][1]){
cnt[p]--; siz[p]--; if(cnt[p]==0) p=0;
}else if(son[p][0]&&!son[p][1]){
rotate(p,1); delet(son[p][1],x);
}else if(!son[p][0]&&son[p][1]){
rotate(p,0); delet(son[p][0],x);
}else{
int d=rd[son[p][0]]>rd[son[p][1]];
rotate(p,d); delet(son[p][d],x);
}
}
pushup(p);
}
int get_rank(int p,int x){
// 空结点,直接返回
if(!p) return 0;
// x=key[p],返回左子树节点数+1
if(key[p]==x) return siz[son[p][0]]+1;
// key[p]<x) x位于右子树,左子树个数+结点个数+x在右子树的位置
if(key[p]<x) return siz[son[p][0]]+cnt[p]+get_rank(son[p][1],x);
//if(key[p]>x) x位于左子树,直接向左边递归
return get_rank(son[p][0],x);
}
int find(int p,int x){
if(!p) return 0;
if(siz[son[p][0]]>=x)
return find(son[p][0],x);
else if(siz[son[p][0]]+cnt[p]<x)
return find(son[p][1],x-cnt[p]-siz[son[p][0]]);
else
return key[p];
}
// 前驱定义为小于x,且最大的数
int pre(int p,int x){
if(!p) return -INF;
if(key[p]>=x) return pre(son[p][0],x);
else return max(key[p],pre(son[p][1],x));
}
// 后继定义为大于x,且最小的数
int suf(int p,int x){
if(!p) return INF;
if(key[p]<=x) return suf(son[p][1],x);
else return min(key[p],suf(son[p][0],x));
}
main(){
int q=read();while(q--){
int x=read();
int y=read();
switch(x){
case 1: insert(rt,y); break;
case 2: delet(rt,y); break;
case 3: printf("%d\n",get_rank(rt,y)); break;
case 4: printf("%d\n",find(rt,y)); break;
case 5: printf("%d\n",pre(rt,y)); break;
case 6: printf("%d\n",suf(rt,y)); break;
}
}
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!