1.存储
struct Node{
int l,r;
int key,val;
int cnt,siz;
}tree[N];
l , r 左儿子,右儿子
key 存储的值
val 随机值
cnt 当前值的个数
siz 包含节点的个数
2.更新父节点
void pushup(int p){
tree[p].siz=tree[tree[p].l].siz+tree[tree[p].r].siz+tree[p].cnt;
}
当前点包含节点个数为: 左儿子 + 右儿子 + 当前数 个数
3.建立新节点
int get_node(int key){
idx++;
tree[idx].key=key;
tree[idx].val=rand();
tree[idx].cnt=tree[idx].siz=1;
return idx;
}
4.建树
void build(){
get_node(-INF),get_node(INF);
root=1,tree[1].r=2;
pushup(root);
}
5.左右旋
void zig(int &p){
int q=tree[p].l;
tree[p].l=tree[q].r,tree[q].r=p,p=q;
pushup(tree[p].r),pushup(p);
}
void zag(int &p){
int q=tree[p].r;
tree[p].r=tree[q].l,tree[q].l=p,p=q;
pushup(tree[p].l),pushup(p);
}
6.插入
void insert(int &p,int key){
if(!p)p=get_node(key);
else if(tree[p].key==key)tree[p].cnt++;
else if(tree[p].key>key){
insert(tree[p].l,key);
if(tree[tree[p].l].val>tree[p].val)zig(p);
}
else {
insert(tree[p].r,key);
if(tree[tree[p].r].val>tree[p].val)zag(p);
}
pushup(p);
}
7. 删除
void remove(int &p,int key){
if(!p)return;
if(tree[p].key==key){
if(tree[p].cnt>1)tree[p].cnt--;
else if(tree[p].l||tree[p].r){
if(!tree[p].r||tree[tree[p].l].val>tree[tree[p].r].val){
zig(p);
remove(tree[p].r,key);
}
else {
zag(p);
remove(tree[p].l,key);
}
}
else p=0;
}
else if(tree[p].key>key)remove(tree[p].l,key);
else remove(tree[p].r,key);
pushup(p);
}
8.通过数值找排名
int get_rank_by_key(int p,int key){
if(!p)return 0;
if(tree[p].key==key)return tree[tree[p].l].siz+1;
if(tree[p].key>key)return get_rank_by_key(tree[p].l,key);
return tree[tree[p].l].siz+tree[p].cnt+get_rank_by_key(tree[p].r,key);
}
9.通过排名找数值
int get_key_by_rank(int p,int rank){
if(!p)return INF;
if(tree[tree[p].l].siz>=rank)return get_key_by_rank(tree[p].l,rank);
if(tree[tree[p].l].siz+tree[p].cnt>=rank)return tree[p].key;
return get_key_by_rank(tree[p].r,rank-tree[tree[p].l].siz-tree[p].cnt);
}
10.找小于x的最大数
int get_pre(int p,int key){
if(!p)return -INF;
if(tree[p].key>=key)return get_pre(tree[p].l,key);
return max(tree[p].key,get_pre(tree[p].r,key));
}
11.找大于x的最小数
int get_next(int p,int key){
if(!p)return INF;
if(tree[p].key<=key)return get_next(tree[p].r,key);
return min(tree[p].key,get_next(tree[p].l,key));
}
Luogu P3369:
#include<bits/stdc++.h>
using namespace std;
#define N 100010
#define INF 2100000000
struct Node{
int l,r;
int key,val;
int cnt,siz;
}tree[N];
int root,idx;
void pushup(int p){
tree[p].siz=tree[tree[p].l].siz+tree[tree[p].r].siz+tree[p].cnt;
}
int get_node(int key){
idx++;
tree[idx].key=key;
tree[idx].val=rand();
tree[idx].cnt=tree[idx].siz=1;
return idx;
}
void build(){
get_node(-INF),get_node(INF);
root=1,tree[1].r=2;
pushup(root);
}
void zig(int &p){
int q=tree[p].l;
tree[p].l=tree[q].r,tree[q].r=p,p=q;
pushup(tree[p].r),pushup(p);
}
void zag(int &p){
int q=tree[p].r;
tree[p].r=tree[q].l,tree[q].l=p,p=q;
pushup(tree[p].l),pushup(p);
}
void insert(int &p,int key){
if(!p)p=get_node(key);
else if(tree[p].key==key)tree[p].cnt++;
else if(tree[p].key>key){
insert(tree[p].l,key);
if(tree[tree[p].l].val>tree[p].val)zig(p);
}
else {
insert(tree[p].r,key);
if(tree[tree[p].r].val>tree[p].val)zag(p);
}
pushup(p);
}
void remove(int &p,int key){
if(!p)return;
if(tree[p].key==key){
if(tree[p].cnt>1)tree[p].cnt--;
else if(tree[p].l||tree[p].r){
if(!tree[p].r||tree[tree[p].l].val>tree[tree[p].r].val){
zig(p);
remove(tree[p].r,key);
}
else {
zag(p);
remove(tree[p].l,key);
}
}
else p=0;
}
else if(tree[p].key>key)remove(tree[p].l,key);
else remove(tree[p].r,key);
pushup(p);
}
int get_rank_by_key(int p,int key){
if(!p)return 0;
if(tree[p].key==key)return tree[tree[p].l].siz+1;
if(tree[p].key>key)return get_rank_by_key(tree[p].l,key);
return tree[tree[p].l].siz+tree[p].cnt+get_rank_by_key(tree[p].r,key);
}
int get_key_by_rank(int p,int rank){
if(!p)return INF;
if(tree[tree[p].l].siz>=rank)return get_key_by_rank(tree[p].l,rank);
if(tree[tree[p].l].siz+tree[p].cnt>=rank)return tree[p].key;
return get_key_by_rank(tree[p].r,rank-tree[tree[p].l].siz-tree[p].cnt);
}
int get_pre(int p,int key){
if(!p)return -INF;
if(tree[p].key>=key)return get_pre(tree[p].l,key);
return max(tree[p].key,get_pre(tree[p].r,key));
}
int get_next(int p,int key){
if(!p)return INF;
if(tree[p].key<=key)return get_next(tree[p].r,key);
return min(tree[p].key,get_next(tree[p].l,key));
}
int main(){
build();
int n;
cin>>n;
while(n--){
int fl,x;
cin>>fl>>x;
if(fl==1)insert(root,x);
else if(fl==2)remove(root,x);
else if(fl==3)cout<<get_rank_by_key(root,x)<<endl;
else if(fl==4)cout<<get_key_by_rank(root,x)<<endl;
else if(fl==5)cout<<get_pre(root,x)<<endl;
else cout<<get_next(root,x)<<endl;
}
return 0;
}