Treap
BST
\(v_i\) 表示点权,\(x\) 表示当前点,\(L\) 表示左子树,\(R\) 表示右子树
在普通二叉树的基础上多一个条件
对于 \(p\in L\),满足 \(v_p\leq v_x\)
对于 \(q\in R\),满足 \(v_x<v_q\)
Treap
但是这样如果 BST 是一条链的话就退化 \(O(n)\),而且很容易卡,考虑Treap
Treap 就是在普通 BST 基础上加上随机点权,随机点权满足堆性质,这样通过随机的堆可以保证树的均匀,即时间复杂度稳定
旋转 Treap
#include<bits/stdc++.h>
using namespace std;
struct node {
int ls, rs;
int val, dat;
int cnt, siz;
#define ls(p) tr[p].ls
#define rs(p) tr[p].rs
#define v(p) tr[p].val
#define d(p) tr[p].dat
#define c(p) tr[p].cnt
#define s(p) tr[p].siz
};
const int INF=1<<30;
struct treap {
int top, rt;
vector<node> tr;
int nnew(int val) {
v(++top)=val;
d(top)=rand();
c(top)=s(top)=1;
return top;
}
void pushup(int p) {
s(p)=s(ls(p))+s(rs(p))+c(p);
}
void build(int siz) {
tr.resize(siz+1);
rt=nnew(-INF);
rs(rt)=nnew(INF);
pushup(rt);
}
int getrk(int p,int val) {
if(p==0) return 0;
if(val==v(p)) return s(ls(p))+1;
if(val<v(p)) return getrk(ls(p),val);
return getrk(rs(p),val)+s(ls(p))+c(p);
}
int getrk(int val) {
return getrk(rt,val)-1;
}
int getval(int p,int rk) {
if(p==0) return INF;
if(rk<=s(ls(p))) return getval(ls(p),rk);
if(rk<=s(ls(p))+c(p)) return v(p);
return getval(rs(p),rk-s(ls(p))-c(p));
}
int getval(int rk) {
return getval(rt,rk+1);
}
void uplt(int &p) {
int q=ls(p);
ls(p)=rs(q), rs(q)=p, p=q;
pushup(rs(p)), pushup(p);
}
void uprt(int &p) {
int q=rs(p);
rs(p)=ls(q), ls(q)=p, p=q;
pushup(ls(p)), pushup(p);
}
void insert(int &p,int val) {
if(p==0) {
p=nnew(val);
return;
}
if(val==v(p)) {
c(p)++, pushup(p);
return;
}
if(val<v(p)) {
insert(ls(p),val);
if(d(p)<d(ls(p))) uplt(p);
}
else {
insert(rs(p),val);
if(d(p)<d(rs(p))) uprt(p);
}
pushup(p);
}
void insert(int val) {
insert(rt,val);
}
int getpre(int val) {
int ans=1, p=rt;
for( ; p; p=val<v(p)?ls(p):rs(p)) {
if(val==v(p)) {
if(ls(p)) {
for(p=ls(p); rs(p); p=rs(p));
ans=p;
}
break;
}
if(v(p)<val&&v(p)>v(ans)) ans=p;
}
return v(ans);
}
int getnxt(int val) {
int ans=2, p=rt;
for( ; p; p=val<v(p)?ls(p):rs(p)) {
if(v(p)==val) {
if(rs(p)) {
for(p=rs(p); ls(p); p=ls(p));
ans=p;
}
break;
}
if(v(p)>val&&v(p)<v(ans)) ans=p;
}
return v(ans);
}
void remove(int &p,int val) {
if(p==0) return;
if(val==v(p)) {
if(c(p)>1) {
c(p)--, pushup(p);
return;
}
if(ls(p)||rs(p)) {
if(rs(p)==0||d(ls(p))>d(rs(p)))
uplt(p), remove(rs(p),val);
else uprt(p), remove(ls(p),val);
pushup(p);
}
else p=0;
return;
}
val<v(p)?remove(ls(p),val):remove(rs(p),val);
pushup(p);
}
void remove(int val) {
remove(rt,val);
}
} qwq;
#include<bits/stdc++.h>
#define int long long
#define MN 101000
using namespace std;
struct node {
int ls, rs;
int val, dat;
int cnt, siz;
#define ls(p) tr[p].ls
#define rs(p) tr[p].rs
#define v(p) tr[p].val
#define d(p) tr[p].dat
#define c(p) tr[p].cnt
#define s(p) tr[p].siz
} tr[MN];
const int INF=(int)1<<60;
int top, rt;
int nnew(int val) {
v(++top)=val;
d(top)=rand();
c(top)=s(top)=1;
return top;
}
void pushup(int p) {
s(p)=s(ls(p))+s(rs(p))+c(p);
}
void build() {
rt=nnew(-INF);
rs(rt)=nnew(INF);
pushup(rt);
}
int getrk(int p,int val) {
if(p==0) return 0;
if(val==v(p)) return s(ls(p))+1;
if(val<v(p)) return getrk(ls(p),val);
return getrk(rs(p),val)+s(ls(p))+c(p);
}
int getval(int p,int rk) {
if(p==0) return INF;
if(rk<=s(ls(p))) return getval(ls(p),rk);
if(rk<=s(ls(p))+c(p)) return v(p);
return getval(rs(p),rk-s(ls(p))-c(p));
}
void uplt(int &p) {
int q=ls(p);
ls(p)=rs(q), rs(q)=p, p=q;
pushup(rs(p)), pushup(p);
}
void uprt(int &p) {
int q=rs(p);
rs(p)=ls(q), ls(q)=p, p=q;
pushup(ls(p)), pushup(p);
}
void insert(int &p,int val) {
if(p==0) {
p=nnew(val);
return;
}
if(val==v(p)) {
c(p)++, pushup(p);
return;
}
if(val<v(p)) {
insert(ls(p),val);
if(d(p)<d(ls(p))) uplt(p);
}
else {
insert(rs(p),val);
if(d(p)<d(rs(p))) uprt(p);
}
pushup(p);
}
int getpre(int val) {
int ans=1, p=rt;
for( ; p; p=val<v(p)?ls(p):rs(p)) {
if(val==v(p)) {
if(ls(p)) {
for(p=ls(p); rs(p); p=rs(p));
ans=p;
}
break;
}
if(v(p)<val&&v(p)>v(ans)) ans=p;
}
return v(ans);
}
int getnxt(int val) {
int ans=2, p=rt;
for( ; p; p=val<v(p)?ls(p):rs(p)) {
if(v(p)==val) {
if(rs(p)) {
for(p=rs(p); ls(p); p=ls(p));
ans=p;
}
break;
}
if(v(p)>val&&v(p)<v(ans)) ans=p;
}
return v(ans);
}
void remove(int &p,int val) {
if(p==0) return;
if(val==v(p)) {
if(c(p)>1) {
c(p)--, pushup(p);
return;
}
if(ls(p)||rs(p)) {
if(rs(p)==0||d(ls(p))>d(rs(p)))
uplt(p), remove(rs(p),val);
else uprt(p), remove(ls(p),val);
pushup(p);
}
else p=0;
return;
}
val<v(p)?remove(ls(p),val):remove(rs(p),val);
pushup(p);
}
signed main() {
srand((unsigned)time(0));
build(); int n;
scanf("%lld", &n);
while(n--) {
int op, x;
scanf("%lld%lld", &op, &x);
if(op==1) insert(rt,x);
if(op==2) remove(rt,x);
if(op==3) printf("%lld\n", getrk(rt,x)-1);
if(op==4) printf("%lld\n", getval(rt,x+1));
if(op==5) printf("%lld\n", getpre(x));
if(op==6) printf("%lld\n", getnxt(x));
}
return 0;
}
#define int long long
#define MN 101000
const int INF=(int)1<<60;
struct treap {
struct node {
int ls, rs;
int val, dat;
int cnt, siz;
#define ls(p) tr[p].ls
#define rs(p) tr[p].rs
#define v(p) tr[p].val
#define d(p) tr[p].dat
#define c(p) tr[p].cnt
#define s(p) tr[p].siz
} tr[MN];
int top, rt;
int nnew(int val) {
v(++top)=val;
d(top)=rand();
c(top)=s(top)=1;
return top;
}
void pushup(int p) {
s(p)=s(ls(p))+s(rs(p))+c(p);
}
void build() {
rt=nnew(-INF);
rs(rt)=nnew(INF);
pushup(rt);
}
int getrk(int p,int val) {
if(p==0) return 0;
if(val==v(p)) return s(ls(p))+1;
if(val<v(p)) return getrk(ls(p),val);
return getrk(rs(p),val)+s(ls(p))+c(p);
}
int getval(int p,int rk) {
if(p==0) return INF;
if(rk<=s(ls(p))) return getval(ls(p),rk);
if(rk<=s(ls(p))+c(p)) return v(p);
return getval(rs(p),rk-s(ls(p))-c(p));
}
void uplt(int &p) {
int q=ls(p);
ls(p)=rs(q), rs(q)=p, p=q;
pushup(rs(p)), pushup(p);
}
void uprt(int &p) {
int q=rs(p);
rs(p)=ls(q), ls(q)=p, p=q;
pushup(ls(p)), pushup(p);
}
void insert(int &p,int val) {
if(p==0) {
p=nnew(val);
return;
}
if(val==v(p)) {
c(p)++, pushup(p);
return;
}
if(val<v(p)) {
insert(ls(p),val);
if(d(p)<d(ls(p))) uplt(p);
}
else {
insert(rs(p),val);
if(d(p)<d(rs(p))) uprt(p);
}
pushup(p);
}
int getpre(int val) {
int ans=1, p=rt;
for( ; p; p=val<v(p)?ls(p):rs(p)) {
if(val==v(p)) {
if(ls(p)) {
for(p=ls(p); rs(p); p=rs(p));
ans=p;
}
break;
}
if(v(p)<val&&v(p)>v(ans)) ans=p;
}
return v(ans);
}
int getnxt(int val) {
int ans=2, p=rt;
for( ; p; p=val<v(p)?ls(p):rs(p)) {
if(v(p)==val) {
if(rs(p)) {
for(p=rs(p); ls(p); p=ls(p));
ans=p;
}
break;
}
if(v(p)>val&&v(p)<v(ans)) ans=p;
}
return v(ans);
}
void remove(int &p,int val) {
if(p==0) return;
if(val==v(p)) {
if(c(p)>1) {
c(p)--, pushup(p);
return;
}
if(ls(p)||rs(p)) {
if(rs(p)==0||d(ls(p))>d(rs(p)))
uplt(p), remove(rs(p),val);
else uprt(p), remove(ls(p),val);
pushup(p);
}
else p=0;
return;
}
val<v(p)?remove(ls(p),val):remove(rs(p),val);
pushup(p);
}
} ;