https://vjudge.net/contest/238179#problem/D
#include<iostream>
#include<algorithm>
#include<string>
#include<stdio.h>
#include<map>
using namespace std;
const int N=110000;
int key[N],father[N],ch[N][2],Size[N],cnt[N];
int root,tot,pre,next;
void Newnode(int &r,int pre,int k)
{
r=++tot;
father[r]=pre;
key[r]=k;
ch[r][0]=ch[r][1]=0;
Size[r]=1;
cnt[r]=1;
}
void clear(int x)
{
Size[x] = father[x] = ch[x][0] = ch[x][1] = cnt[x] = key[x] = 0;
}
void up(int x)
{
if(x)
{
Size[x] = cnt[x];
if(ch[x][0])
Size[x] += Size[ch[x][0]];
if(ch[x][1])
Size[x] += Size[ch[x][1]];
}
}
void Rotate(int x,int kind)
{
int y=father[x];
ch[y][!kind]=ch[x][kind];
father[ch[x][kind]]=y;
if(father[y])
ch[father[y]][ch[father[y]][1]==y]=x;
father[x]=father[y];
ch[x][kind]=y;
father[y]=x;
up(y);
}
void splay(int x,int goal)
{
while(father[x]!=goal)
{
int y=father[x];
if(father[y]==goal)
Rotate(x,ch[y][0]==x);
else
{
int kind=(ch[father[y]][0]==y);
if(ch[y][kind]==x)
{
Rotate(x,!kind);
Rotate(x,kind);
}
else
{
Rotate(y,kind);
Rotate(x,kind);
}
}
}
if(goal==0)
root=x;
up(x);
}
void Insert(int x)
{
if(root==0)
{
Newnode(root,0,x);
return;
}
int now=root;
while(true)
{
Size[now]++;
if(x==key[now])
{
cnt[now]++;
return;
}
if(ch[now][key[now]<x]==0)//之前错误的原因是
//int y=ch[now][key[now]<x];Newnode(y,now,x);
//这样就导致ch[now][key[now]<x]值没有改变,就超时了
{
Newnode(ch[now][key[now]<x],now,x);
now=ch[now][key[now]<x];
break;
}
now=ch[now][key[now]<x];
}
splay(now,0);
}
void del(int x)
{
int r=root;
while(1)
{
if(key[r]==x)
break;
r=ch[r][key[r]<x];
}
splay(r,0);//应该先让r成为根节点,当cnt[r]>1,才能直接--,因为如果不改变r上面的所有节点的值都改变了,很麻烦
if(cnt[r]>1)
{
cnt[r]--;
Size[r]--;
return;
}
int rr=root;
if(ch[r][0]&&!ch[r][1])
{
father[ch[r][0]]=0;
root=ch[r][0];
clear(rr);
}
else if(!ch[r][0]&&ch[r][1])
{
father[ch[r][1]]=0;
root=ch[r][1];
clear(rr);
}
else if(!ch[r][0]&&!ch[r][1])
{
root=0;
clear(rr);
}
else
{
int k=ch[r][1];
while(ch[k][0])
{
k=ch[k][0];
}
splay(k,root);
ch[k][0]=ch[root][0];
father[ch[root][0]]=k;
father[k]=0;
root=k;
clear(rr);
up(root);//修改完根节点,改变根节点的size;
}
}
void Get_pre(int i,int x)
{
if(i==0)
return ;
if(key[i]<x)
{
pre=key[i];
Get_pre(ch[i][1],x);
}
else
Get_pre(ch[i][0],x);
}
void Get_next(int i,int x)
{
if(i==0)
return;
if(key[i]>x)
{
next=key[i];
Get_next(ch[i][0],x);
}
else
Get_next(ch[i][1],x);
}
int Find_x(int v)//这个函数刚开始就写错了,,,,,
{
int now = root, ans = 0;
while(1)
{
if(v < key[now])
now = ch[now][0]; //左
else
{
if(ch[now][0])
ans += Size[ch[now][0]];
if(v == key[now])
{
splay(now,0);
return ans + 1;
}
ans += cnt[now];
now = ch[now][1];//右
}
}
}
int Find_k(int i,int k)
{
if(i==0)
return -1;
if(Size[ch[i][0]]>=k)
return Find_k(ch[i][0],k);
if(Size[ch[i][0]]+cnt[i]>=k)
return key[i];
return Find_k(ch[i][1],k-Size[ch[i][0]]-cnt[i]);
}
int main()
{
int n;
scanf("%d",&n);
root=tot=0;
for(int i=1; i<=n; i++)
{
int a,b;
scanf("%d%d",&a,&b);
if(a==1)
Insert(b);
else if(a==2)
del(b);
else if(a==3)
printf("%d\n",Find_x(b));
else if(a==4)
printf("%d\n",Find_k(root,b));
else if(a==5)
{
Get_pre(root,b);
printf("%d\n",pre);
}
else if(a==6)
{
Get_next(root,b);
printf("%d\n",next);
}
}
return 0;
}