题目:普通平衡树
参考:
代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 100000
#define inf (1<<30)
struct Node {
int val;
int cnt;
int fa,ch[2];
int size;
void init() {
val=ch[0]=ch[1]=0;
cnt=size=1;
}
};
Node a[maxn+5];
int n=0,rt=0; //节点个数,根节点
void pushup(int x) {
a[x].size=a[a[x].ch[0]].size+a[a[x].ch[1]].size+a[x].cnt;
}
void rotate(int x) { //旋转
int y=a[x].fa,z=a[y].fa;
int k=(a[y].ch[1]==x); //x是y的哪边儿子
a[z].ch[a[z].ch[1]==y]=x,a[x].fa=z;
a[y].ch[k]=a[x].ch[k^1],a[a[x].ch[k^1]].fa=y;
a[x].ch[k^1]=y,a[y].fa=x;
pushup(y),pushup(x);
}
void splay(int x,int k) { //伸展
while(a[x].fa!=k) {
int y=a[x].fa,z=a[y].fa; //父亲和爷爷
if(z!=k) {
if((a[y].ch[0]==x)^(a[z].ch[0]==y)) rotate(x); //在一条折线
else rotate(y); //一条直线
}
rotate(x);
}
if(!k) rt=x;
}
void insert(int x) { //插入
int u=rt,fth=0;
while(u&&a[u].val!=x) { //顺着bst往下找插入的位置
fth=u; //记录插入位置的父节点
u=a[u].ch[x>a[u].val];
}
if(u) { //存在这个值
a[u].cnt++;
splay(u,0);
return ;
}
n++; //增加节点总数
a[n].init();
if(fth) a[fth].ch[x>a[fth].val]=n;
a[n].val=x;
a[n].fa=fth;
splay(n,0); //把最近访问的节点splay到根
}
void find(int x) { //查找排名
int u=rt;
while(a[u].ch[x>a[u].val]&&x!=a[u].val) {
u=a[u].ch[x>a[u].val];
}
splay(u,0);
}
int nxt(int x,int k) { //查找前驱/后继
find(x);
int u=rt;
if((a[u].val<x&&!k)||(a[u].val>x&&k)) return u;
u=a[u].ch[k];
while(a[u].ch[k^1]) u=a[u].ch[k^1];
return u;
}
void del(int x) { //删除
int y=nxt(x,0),z=nxt(x,1);
splay(y,0),splay(z,y);
int del=a[z].ch[0];
if(a[del].cnt>1) {
a[del].cnt--;
splay(del,0);
} else a[z].ch[0]=0;
}
int findv(int x) { //查找值
int u=rt;
while(true) {
int y=a[u].ch[0];
if(x>a[y].size+a[u].cnt) {
x-=a[y].size+a[u].cnt;
u=a[u].ch[1];
} else if(a[y].size>=x) u=y;
else return a[u].val;
}
}
int main() {
int m;
scanf("%d",&m);
insert(-inf);
insert(+inf);
while(m--) {
int opr,x;
scanf("%d%d",&opr,&x);
if(opr==1) insert(x);
if(opr==2) del(x);
if(opr==3) find(x),printf("%d\n",a[a[rt].ch[0]].size);
if(opr==4) printf("%d\n",findv(x+1));
if(opr==5) printf("%d\n",a[nxt(x,0)].val);
if(opr==6) printf("%d\n",a[nxt(x,1)].val);
}
return 0;
}