思路:Splay模板题
代码:
#include<bits/stdc++.h>
using namespace std;
#define MAXN 1000000
//f[i]表示i的父结点,ch[i][0]表示i的左儿子,ch[i][1]表示i的右儿子,
//key[i]表示i的关键字(即结点i代表的那个数字),cnt[i]表示i结点的关键字出现的次数(相当于权值),
//size[i]表示包括i的这个子树的大小;sz为整棵树的大小,root为整棵树的根。
int ch[MAXN][2],f[MAXN],size[MAXN],cnt[MAXN],key[MAXN];
int sz,root;
//将当前点的各项值都清0(用于删除之后)
void clear(int x)
{
ch[x][0]=ch[x][1]=f[x]=size[x]=cnt[x]=key[x]=0;
}
//判断当前点是它父结点的左儿子还是右儿子
bool get(int x)
{
return ch[f[x]][1]==x;
}
//更新当前点的size值(用于发生修改之后)
void update(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 old=f[x],oldf=f[old],whichx=get(x);
ch[old][whichx]=ch[x][whichx^1];
f[ch[old][whichx]]=old;
ch[x][whichx^1]=old;
f[old]=x;
f[x]=oldf;
if(oldf)
ch[oldf][ch[oldf][1]==old]=x;
update(old);
update(x);
}
void splay(int x)
{
for(int fa;fa=f[x];rotate(x))
if(f[fa])
rotate((get(x)==get(fa))?fa:x);
root=x;
}
void insert(int v)
{
if(root==0)
{
sz++;
ch[sz][0]=ch[sz][1]=f[sz]=0;
key[sz]=v;
cnt[sz]=1;
size[sz]=1;
root=sz;
return;
}
int now=root,fa=0;
while(1)
{
if(key[now]==v)
{
cnt[now]++;
update(now);
update(fa);
splay(now);
break;
}
fa=now;
now=ch[now][key[now]<v];
if(now==0)
{
sz++;
ch[sz][0]=ch[sz][1]=0;
key[sz]=v;
size[sz]=cnt[sz]=1;
ch[fa][key[fa]<v]=sz;
f[sz]=fa;
update(fa);
splay(sz);
break;
}
}
}
//查询x的排名
int find(int v)
{
int ans=0,now=root;
while(1)
{
if(v<key[now])
{
now=ch[now][0];
}
else
{
ans+=(ch[now][0]?size[ch[now][0]]:0);
if(v==key[now])
{
splay(now);return ans+1;
}
ans+=cnt[now];
now=ch[now][1];
}
}
}
//找到排名为x的点
int findx(int x)
{
int now=root;
while(1)
{
if(ch[now][0]&&x<=size[ch[now][0]])
{
now=ch[now][0];
}
else
{
int temp=(ch[now][0]?size[ch[now][0]]:0)+cnt[now];
if(x<=temp)
return key[now];
x-=temp;
now=ch[now][1];
}
}
}
int pre()
{
int now=ch[root][0];
while(ch[now][1])
{
now=ch[now][1];
}
return now;
}
int next()
{
int now=ch[root][1];
while(ch[now][0])now=ch[now][0];
return now;
}
void del(int x)
{
int whatever=find(x);
if(cnt[root]>1){cnt[root]--;update(root);return;}
if(!ch[root][0]&&!ch[root][1]){clear(root);root=0;return;}
if(!ch[root][0])
{
int oldroot=root;
root=ch[root][1];
f[root]=0;
clear(oldroot);
return;
}
else if(!ch[root][1])
{
int oldroot=root;
root=ch[root][0];
f[root]=0;
clear(oldroot);
return ;
}
int leftc=pre(),oldroot=root;
splay(leftc);
f[ch[oldroot][1]]=root;
ch[root][1]=ch[oldroot][1];
clear(oldroot);
update(root);
return;
}
int main()
{
int n,opt,x;
scanf("%d",&n);
for (int i=1;i<=n;++i){
scanf("%d%d",&opt,&x);
if(opt==1)
{
insert(x);
}
else if(opt==2)
{
del(x);
}
else if(opt==3)
{
printf("%d\n",find(x));
}
else if(opt==4)
{
printf("%d\n",findx(x));
}
else if(opt==5)
{
insert(x);
printf("%d\n",key[pre()]);
del(x);
}
else
{
insert(x);
printf("%d\n",key[next()]);
del(x);
}
}
return 0;
}