splay普通平衡树coedvs4543

来源:互联网 发布:java界面布局类型 编辑:程序博客网 时间:2024/06/08 16:43

题目描述

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

插入x数

删除x数(若有多个相同的数,因只删除一个)

查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)

查询排名为x的数

求x的前驱(前驱定义为小于x,且最大的数)

求x的后继(后继定义为大于x,且最小的数)
输入输出格式

输入格式:

第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号( 1 \leq opt \leq 6 1≤opt≤6 )

输出格式:

对于操作3,4,5,6每行输出一个数,表示对应答案

输入输出样例

输入样例#1:

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
输出样例#1:
106465
84185
492737

说明

时空限制:1000ms,128M

来源:Tyvj1728 原名:普通平衡树

注意细节

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXN=1000001;int size[MAXN],f[MAXN],key[MAXN],cnt[MAXN],ch[MAXN][2];int root = 0,n,sz = 0;void up(int x){    if(x)    {        size[x]=cnt[x];        if(ch[x][1]) size[x]+=size[ch[x][1]];        if(ch[x][0]) size[x]+=size[ch[x][0]];        return;    }}void clear(int x){    key[x]=cnt[x]=f[x]=size[x]=cnt[x]=ch[x][1]=ch[x][0]=0;    return;}bool get(int x){    return ch[f[x]][1]==x;}void rotate(int x){    int y=f[x],z=f[y],k=get(x);    ch[y][k]=ch[x][k^1];    f[ch[y][k]]=y;    ch[x][k^1]=y;    f[x]=z;    f[y]=x;    if(z) ch[z][ch[z][1]==y]=x;    up(y),up(x);    return;}void splay(int x){    for(int fa;fa=f[x];rotate(x))    if(f[fa]) rotate(get(x)==get(fa)?fa:x);    root=x;//别忘了    return;}void insert(int x){    if(root==0)     {        sz++;        size[sz]=cnt[sz]=1;        ch[sz][0]=ch[sz][1]=0;        f[sz]=0;        root=sz;//别忘了        key[sz]=x;        return;    }    int now=root,fa=0;    while(true)    {        if(x==key[now])        {            cnt[now]++;            up(now),up(fa);            splay(now);            break;        }        fa=now;        now=ch[now][key[now]<x];        if(!now)        {            sz++;            ch[sz][0]=ch[sz][1]=0;            f[sz]=fa;            size[sz]=cnt[sz]=1;            ch[fa][key[fa]<x]=sz;//!!!!!别忘了!!!!!!            key[sz]=x;            up(fa);            splay(sz);            break;        }    }    return;}int find(int x){    int now=root,ans=0;    while(true)    {        if(x<key[now]) now=ch[now][0];        else         {            ans+=(ch[now][0]?size[ch[now][0]]:0);            if(x==key[now])            {                splay(now);                return ans+1;            }            ans+=cnt[now];            now=ch[now][1];        }     }}int findx(int x){    int now=root;    while(true)    {        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 nxt(){    int now=ch[root][1];    while(ch[now][0]) now=ch[now][0];    return now;}void del(int x){    int ss=find(x);    if(cnt[root]>1)    {        cnt[root]--;        up(root);        return;    }    if(!ch[root][0] && !ch[root][1])    {        clear(root);        root=0;        return;    }    if(!ch[root][1])     {        int t=root;        root=ch[root][0];        f[root]=0;        clear(t);        return;    }    if(!ch[root][0])    {        int t=root;        root=ch[root][1];        f[root]=0;        clear(t);        return;    }    int ll=pre(),y=root;//!!!!!!    splay(ll);    ch[root][1]=ch[y][1];    f[ch[y][1]]=root;    clear(y);    up(root);    return;}int main(){    int opt,x;    cin>>n;    for(int i=1;i<=n;i++)    {        scanf("%d%d",&opt,&x);        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",key[pre()]),del(x);break;            case 6:insert(x);printf("%d\n",key[nxt()]),del(x);break;        }    }    return 0;}
原创粉丝点击