BST(Binary Search Tree)二叉搜索树
BST(Binary Search Tree)二叉搜索树
blog
是一棵空树或具有以下几种性质(简而言之,就是中序遍历有序)的树
- 若左子树不空,则左子树上所有结点的值均小于它的根结点的值
- 若右子树不空,则右子树上所有结点的值均大于它的根结点的值
- 左、右子树也分别为二叉搜索树
- 没有权值相等的结点。
遇到多个相等的数该怎么办呢,显然我们可以多加一个计数器
那么我们的每一个节点都包含以下几个信息:
- 当前节点的权值,也就是序列里的数
- 左孩子的下标和右孩子的下标,如果没有则为0
- 计数器,代表当前的值出现了几遍
- 子树大小和自己的大小的和
至于为什么要有4.我们放到后面讲。
节点是这样的:
struct node{
int val,ls,rs,cnt,siz;
}tree[500010];
其中 val是权值, ls rs 是左/右 孩子的下标, cnt 是当前的权值出现了几次, siz 是子树大小和自己的大小的和。
#include <iostream>
#include <cstdio>
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
const int N=500005;
const int INF=2147483647;
int n,tree_cnt;
struct TREE{
int cnt,ls,rs,val,siz;
}t[N];
void insert(int x,int v){
t[x].siz++;
if(t[x].val==v){t[x].cnt++;return;}
if(t[x].val>v){
if(!t[x].ls){
tree_cnt++;
t[tree_cnt].cnt=t[tree_cnt].siz=1;
t[tree_cnt].val=v;
t[x].ls=tree_cnt;
}else { insert(t[x].ls,v); }
}else{
if(!t[x].rs){
tree_cnt++;
t[tree_cnt].cnt=t[tree_cnt].siz=1;
t[tree_cnt].val=v;
t[x].rs=tree_cnt;
}else { insert(t[x].rs,v); }
}
}
int get_pre(int x,int v,int ans){//ans 是目前找到的比 val小的数的最大值
if(t[x].val>=v){
if(t[x].ls==0) return ans;
else return get_pre(t[x].ls,v,ans);
}else{
if(t[x].rs==0) return t[x].val<v?t[x].val:ans;
if(t[x].cnt) return get_pre(t[x].rs,v,t[x].val);//更新ans
else return get_pre(t[x].rs,v,ans);
}
}
int get_nxt(int x,int v,int ans){
if(t[x].val<=v){
if(t[x].rs==0) return ans;
else return get_nxt(t[x].rs,v,ans);
}else{
if(t[x].ls==0) return t[x].val>v?t[x].val:ans;
if(t[x].cnt) return get_nxt(t[x].ls,v,t[x].val);//更新ans
else return get_nxt(t[x].ls,v,ans);
}
}
int get_rk(int x,int v){
if(x==0) return 0;
if(v==t[x].val) return t[t[x].ls].siz+1;
if(v<t[x].val) return get_rk(t[x].ls,v);
return get_rk(t[x].rs,v)+t[t[x].ls].siz+t[x].cnt;
}
int get_val(int x,int rk){
if(x==0) return INF;
if(t[t[x].ls].siz>=rk) return get_val(t[x].ls,rk);
if(t[t[x].ls].siz+t[x].cnt>=rk) return t[x].val;
return get_val(t[x].rs,rk-t[t[x].ls].siz-t[x].cnt);
}
int main(){
n=read();
int opt,x;
while(n--){
opt=read();x=read();
if(opt==1) printf("%d\n",get_rk(1,x)+1);
else if(opt==2) printf("%d\n",get_val(1,x));
else if(opt==3) printf("%d\n",get_pre(1,x,-INF));
else if(opt==4) printf("%d\n",get_nxt(1,x,INF));
else{
if(!tree_cnt){
tree_cnt++;
t[tree_cnt].cnt=t[tree_cnt].siz=1;
t[tree_cnt].val=x;
}
else insert(1,x);
}
}
return 0;
}