题目链接:戳这里
3224: Tyvj 1728 普通平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 17768 Solved: 7799
[ Submit][ Status][ Discuss]
Description
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
Input
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
Output
对于操作3,4,5,6每行输出一个数,表示对应答案
Sample Input
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
Sample Output
106465
84185
492737
84185
492737
HINT
1.n的数据范围:n<=100000
2.每个数的数据范围:[-2e9,2e9]
代码:
#include<bits/stdc++.h>
#define maxn 100005
using namespace std;
typedef long long LL;
int read()
{
char c;int sum=0,f=1;c=getchar();
while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0' && c<='9'){sum=sum*10+c-'0';c=getchar();}
return sum*f;
}
int n,opt,x;
int fa[maxn],son[maxn][2],val[maxn],cnt[maxn],size[maxn],sz,root;
void clear(int x)
{
son[x][1]=son[x][0]=fa[x]=val[x]=cnt[x]=size[x]=0;
}
bool getson(int x)
{
return son[fa[x]][1]==x;
}
void pushup(int x)
{
if(x)
{
size[x]=cnt[x];
if(son[x][0]) size[x]+=size[son[x][0]];
if(son[x][1]) size[x]+=size[son[x][1]];
}
}
void rotate(int x)
{
int y=fa[x],z=fa[y],s=getson(x);
son[y][s]=son[x][s^1];fa[son[y][s]]=y;
fa[y]=x;son[x][s^1]=y;
fa[x]=z;
if(z)
son[z][son[z][1]==y]=x;
pushup(y);pushup(x);
}
void splay(int x,int k)
{
for(int y;(y=fa[x])!=k;rotate(x))
if(fa[y]!=k)
rotate((getson(x)==getson(y))?y:x);
if(!k) root=x;
}
void insert(int x)
{
if(root==0)
{
sz++;root=sz;
son[sz][0]=son[sz][1]=fa[sz]=0;
val[sz]=x;size[sz]=cnt[sz]=1;
return;
}
int now=root,f=0;
while(1)
{
if(val[now]==x){cnt[now]++;pushup(now);pushup(f);splay(now,0);break;}
f=now;
now=son[now][val[now]<x];
if(now==0)
{
sz++;
son[sz][0]=son[sz][1]=0;fa[sz]=f;
val[sz]=x;size[sz]=cnt[sz]=1;
son[f][val[f]<x]=sz;
pushup(f);
splay(sz,0);
break;
}
}
}
int find(int x)
{
int ans=0,now=root;
while(1)
{
if(x<val[now])
now=son[now][0];
else
{
ans+=(son[now][0]?size[son[now][0]]:0);
if(x==val[now])
{
splay(now,0);
return ans+1;
}
ans+=cnt[now];
now=son[now][1];
}
}
}
int findx(int x)
{
int now=root;
while(1)
{
if(son[now][0] && x<=size[son[now][0]])
now=son[now][0];
else
{
int temp=(son[now][0]?size[son[now][0]]:0)+cnt[now];
if(x<=temp)
return val[now];
x-=temp;
now=son[now][1];
}
}
}
int pre()
{
int now=son[root][0];
while(son[now][1])
now=son[now][1];
return now;
}
int nex()
{
int now=son[root][1];
while(son[now][0])
now=son[now][0];
return now;
}
void del(int x)
{
find(x);
if(cnt[root]>1){cnt[root]--;return;}
if(!son[root][0] && !son[root][1]){clear(root);root=0;return;}
int oldroot=root;
if(!son[root][0])
{
root=son[root][1];fa[root]=0;clear(oldroot);return;
}
else if(!son[root][1])
{
root=son[root][0];fa[root]=0;clear(oldroot);return;
}
splay(pre(),0);
fa[son[oldroot][1]]=root;
son[root][1]=son[oldroot][1];
clear(oldroot);pushup(root);
}
int main()
{
n=read();
for(int i=1;i<=n;i++)
{
opt=read();x=read();
switch (opt)
{
case 1:insert(x);break;
case 2:del(x);break;
case 3:printf("%d\n",find(x));break;
case 4:printf("%d\n",findx(x));break;
case 5:insert(x);printf("%d\n",val[pre()]);del(x);break;
case 6:insert(x);printf("%d\n",val[nex()]);del(x);break;
}
}
return 0;
}