平衡树板子
平衡树写法真的是太nm多了
首先是 \(Treap\) (当时比较sb于是写了指针
//#define LawrenceSivan
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define re register
#define INF 1<<30
struct node{
ll key;
int rank;
int cnt;
int size;
node *son[2];
bool operator < (const node &a)const{return rank<a.rank;}
node(ll val):key(val),rank(rand()),cnt(1),size(1){
son[0]=son[1]=NULL;
}
inline void update(){
size=cnt;
if(son[0]!=NULL)size+=son[0]->size;
if(son[1]!=NULL)size+=son[1]->size;
}
};
node *root;
inline void rotate(node* &o,int d){
node *k=o->son[d^1];
o->son[d^1]=k->son[d];
k->son[d]=o;
o->update();
k->update();
o=k;
}
void insert(node* &o,ll k){
if(!o) o=new node(k);
else if(o->key==k) o->cnt++;
else{
if(o->key>k)insert(o->son[0],k);
else insert(o->son[1],k);
if(o->son[0]&&(*o<*o->son[0]))rotate(o,1);
else if(o->son[1]&&(*o<*o->son[1]))rotate(o,0);
}
o->update();
}
void remove(node* &o,ll k){
if(o->key==k){
if(o->cnt>1) o->cnt--;
else{
if(o->son[0]==NULL&&o->son[1]==NULL){
delete o;
o=NULL;
return;
}
else if(o->son[0]&&o->son[1]){
if(*o->son[0]<*o->son[1]){
rotate(o,0);
remove(o->son[0],k);
}
else{
rotate(o,1);
remove(o->son[1],k);
}
}
else if(o->son[0]){
rotate(o,1);
remove(o->son[1],k);
}
else{
rotate(o,0);
remove(o->son[0],k);
}
}
}
else if(k<o->key)remove(o->son[0],k);
else remove(o->son[1],k);
o->update();
}
int kth(node* o,ll x){
if(!o)return 1;
int tmp= (o->son[0]?o->son[0]->size:0);
if(o->key==x)return tmp+1;
else if(x<o->key)return kth(o->son[0],x);
else return tmp+o->cnt+kth(o->son[1],x);
}
ll find(node* o,int k){
if(!o)return 0;
int tmp= (o->son[0]?o->son[0]->size:0);
if(tmp<k&&k<=tmp+o->cnt)return o->key;
else if(k<=tmp)return find(o->son[0],k);
else return find(o->son[1],k-tmp-o->cnt);
}
void pre(node* o,ll k,ll &ans){
if(o==NULL)return;
if(o->key<k){
if(o->key>ans)ans=o->key;
pre(o->son[1],k,ans);
}
else pre(o->son[0],k,ans);
}
void nxt(node* o,ll k,ll &ans){
if(o==NULL)return;
if(o->key>k){
if(o->key<ans)ans=o->key;
nxt(o->son[0],k,ans);
}
else nxt(o->son[1],k,ans);
}
ll n,T,op;
ll x,ans;
inline ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
return x*f;
}
int main(){
#ifdef LawrenceSivan
freopen("aa.in","r",stdin);
freopen("aa.out","w",stdout);
#endif
srand(time(0));
T=read();
while(T--){
op=read();x=read();
if(op==1)insert(root,x);
if(op==2)remove(root,x);
if(op==3){
ans=kth(root,x);
printf("%lld\n",ans);
}
if(op==4){
ans=find(root,x);
printf("%lld\n",ans);
}
if(op==5){
ll anss=-INF;
pre(root,x,anss);
ans=anss;
printf("%lld\n",ans);
}
if(op==6){
ll anss=INF;
nxt(root,x,anss);
ans=anss;
printf("%lld\n",ans);
}
}
return 0;
}
之后是 \(Splay\)
//#define LawrenceSivan
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define re register
const int maxn=1e5+5;
#define INF 0x7fffffff
#define ls(x) t[(x)].ch[0]
#define rs(x) t[(x)].ch[1]
int n,root,tot;
struct node{
int ch[2];
int fa;
int cnt;//¸öÊý
int val;
int son;//¶ù×ÓÊýÁ¿
}t[maxn];
inline void push_up(int x){
t[x].son=t[ls(x)].son+t[rs(x)].son+t[x].cnt;
}
inline void rotate(int x){
int f=t[x].fa;
int g=t[f].fa;
int s=rs(f)==x;
t[g].ch[rs(g)==f]=x;t[x].fa=g;
t[f].ch[s]=t[x].ch[s^1];t[t[x].ch[s^1]].fa=f;
t[x].ch[s^1]=f;t[f].fa=x;
push_up(f),push_up(x);
}
inline void Splay(int x,int goal){
while(t[x].fa!=goal){
int f=t[x].fa;
int g=t[f].fa;
if(g!=goal){
(ls(f)==x)^(ls(g)==f)?rotate(x):rotate(f);
}
rotate(x);
}
if(goal==0){
root=x;
}
}
inline void insert(int x){
int u=root,f=0;
while(u&&t[u].val!=x){
f=u;
u=t[u].ch[x>t[u].val];
}
if(u) t[u].cnt++;
else{
u=++tot;
if(f) t[f].ch[x>t[f].val]=u;
ls(tot)=0;rs(tot)=0;
t[tot].fa=f;
t[tot].val=x;
t[tot].cnt=1;
t[tot].son=1;
}
Splay(u,0);
}
inline void find(int x){
int u=root;
if(!u)return;
while(t[u].ch[x>t[u].val]&&x!=t[u].val){
u=t[u].ch[x>t[u].val];
}
Splay(u,0);
}
inline int Nxt(int x,int f){
find(x);
int u=root;
if((t[u].val>x&&f)||(t[u].val<x&&!f))return u;
u=t[u].ch[f];
while(t[u].ch[f^1])u=t[u].ch[f^1];
return u;
}
inline void Delete(int x){
int pre=Nxt(x,0);
int nxt=Nxt(x,1);
Splay(pre,0);Splay(nxt,pre);
int del=ls(nxt);
if(t[del].cnt>1){
t[del].cnt--;
Splay(del,0);
}
else ls(nxt)=0;
}
inline int kth(int x){
int u=root;
if(t[u].son<x)return 0;
while(1){
int s=ls(u);
if(x>t[s].son+t[u].cnt){
x-=t[s].son+t[u].cnt;
u=rs(u);
}
else if(t[s].son>=x)u=s;
else return t[u].val;
}
}
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^48);ch=getchar();}
return x*f;
}
int main(){
#ifdef LawrenceSivan
freopen("aa.in","r",stdin);
freopen("aa.out","w",stdout);
#endif
n=read();
insert(-INF);
insert(INF);
while(n--){
int op=read();
if(op==1){
int x=read();
insert(x);
}
else if(op==2){
int x=read();
Delete(x);
}
else if(op==3){
int x=read();
find(x);
printf("%d\n",t[ls(root)].son);
}
else if(op==4){
int x=read();
printf("%d\n",kth(x+1));
}
else if(op==5){
int x=read();
printf("%d\n",t[Nxt(x,0)].val);
}
else if(op==6){
int x=read();
printf("%d\n",t[Nxt(x,1)].val);
}
}
return 0;
}
之后是替罪羊,
//#define LawrenceSivan
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define re register
const double alpha=0.7;
#define INF 0x3f3f3f3f
int n,op,x;
struct node{
node *l,*r;
int val,size,cnt;
bool del;
bool isbad(){
return l->cnt>alpha*cnt||r->cnt>alpha*cnt;
}
void update(){
size=!del+l->size+r->size;
cnt=l->cnt+r->cnt+1;
}
};
node *null,*root,**badtag;
void dfs(node* o,vector<node*> &v){
if(o==null)return;
dfs(o->l,v);
if(!o->del)v.push_back(o);
dfs(o->r,v);
if(o->del)delete o;
}
node* build(vector<node*> &v,int l,int r){
if(l>=r)return null;
int mid=(l+r)>>1;
node *o=v[mid];
o->l=build(v,l,mid);
o->r=build(v,mid+1,r);
o->update();
return o;
}
void rebuild(node* &o){
vector<node*> v;
dfs(o,v);
o=build(v,0,v.size());
}
void Insert(node* &o,int x){
if(o==null){
o=new node;
o->l=o->r=null;
o->del=false;
o->size=o->cnt=1;
o->val=x;
return;
}
else{
o->size++;
o->cnt++;
if(x>=o->val)Insert(o->r,x);
else Insert(o->l,x);
if(o->isbad())badtag=&o;
else if(badtag!=&null) o->cnt-=(*badtag)->cnt-(*badtag)->size;
}
}
void insert(node* &o,int x){
badtag=&null;
Insert(o,x);
if(badtag!=&null)rebuild(*badtag);
}
int Rank(node *o,int x){
int ans=1;
while(o!=null){
if(o->val>=x)o=o->l;
else{
ans+=o->l->size+!o->del;
o=o->r;
}
}
return ans;
}
int kth(node *o,int x){
while(o!=null){
if(!o->del&&o->l->size+1==x)return o->val;
if(o->l->size>=x)o=o->l;
else{
x-=o->l->size+!o->del;
o=o->r;
}
}
}
void remove(node *o,int k){
if(!o->del&&k==o->l->size+1){
o->del=1;
o->size--;
return;
}
o->size--;
if(k<=o->l->size+!o->del)remove(o->l,k);
else remove(o->r,k-o->l->size-!o->del);
}
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^48);ch=getchar();}
return x*f;
}
int main(){
#ifdef LawrenceSivan
freopen("aa.in","r",stdin);
freopen("aa.out","w",stdout);
#endif
null=new node;
root=null;
n=read();
while(n--){
op=read();x=read();
if(op==1)insert(root,x);
if(op==2)remove(root,Rank(root,x));
if(op==3)printf("%d\n",Rank(root,x));
if(op==4)printf("%d\n",kth(root,x));
if(op==5)printf("%d\n",kth(root,Rank(root,x)-1));
if(op==6)printf("%d\n",kth(root,Rank(root,x+1)));
}
return 0;
}