BZOJ3224: Tyvj 1728 普通平衡树

【传送门:BZOJ3224


简要题意:

  有一个数列,有6种操作:

  1. 插入x数
  2. 删除x数(若有多个相同的数,因只删除一个)
  3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
  4. 查询排名为x的数
  5. 求x的前驱(前驱定义为小于x,且最大的数)
  6. 求x的后继(后继定义为大于x,且最小的数)


题解:

  SPLAY模版,例题


参考代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
using namespace std;
struct trnode
{
    int d,n,c,f,son[2];
}tr[110000];int len,root;
void update(int x)
{
    int lc=tr[x].son[0],rc=tr[x].son[1];
    tr[x].c=tr[lc].c+tr[rc].c+tr[x].n;
}
void add(int d,int f)
{
    len++;
    tr[len].d=d;tr[len].n=1;tr[len].c=1;
    tr[len].f=f;
    if(d<tr[f].d) tr[f].son[0]=len;
    else tr[f].son[1]=len; 
    tr[len].son[0]=tr[len].son[1]=0;
}
void rotate(int x,int w)
{
    int f=tr[x].f,ff=tr[f].f;
    int r,R;
    r=tr[x].son[w];R=f;
    tr[R].son[1-w]=r;
    if(r!=0) tr[r].f=R;
    r=x;R=ff;
    if(tr[R].son[0]==f) tr[R].son[0]=r;
    else tr[R].son[1]=r;
    tr[r].f=R;
    r=f;R=x;
    tr[R].son[w]=r;
    tr[r].f=R;
    update(f);
    update(x);
}
void splay(int x,int rt)
{
    while(tr[x].f!=rt)
    {
        int f=tr[x].f,ff=tr[f].f;
        if(ff==rt)
        {
            if(tr[f].son[0]==x) rotate(x,1);
            else rotate(x,0);
        } 
        else
        {
            if(tr[ff].son[0]==f&&tr[f].son[0]==x){rotate(f,1);rotate(x,1);}
            else if(tr[ff].son[1]==f&&tr[f].son[1]==x){rotate(f,0);rotate(x,0);}
            else if(tr[ff].son[0]==f&&tr[f].son[1]==x){rotate(x,0);rotate(x,1);}
            else if(tr[ff].son[1]==f&&tr[f].son[0]==x){rotate(x,1);rotate(x,0);}   
        }
    }
    if(rt==0) root=x;
}
int findip(int d)
{
    int x=root;
    while(tr[x].d!=d)
    {
        if(d<tr[x].d)
        {
            if(tr[x].son[0]==0) break;
            else x=tr[x].son[0];
        }
        else
        {
            if(tr[x].son[1]==0) break;
            else x=tr[x].son[1];
        }
    }
    return x;
}
void ins(int d)
{
    if(root==0) {add(d,0);root=len;return ;}
    int x=findip(d);
    if(tr[x].d==d) 
    {
        tr[x].n++;
        update(x);
        splay(x,0);
    }
    else
    { 
        add(d,x);
        update(x);
        splay(len,0);
    }
}
void del(int d)
{
    int x=findip(d);splay(x,0);
    if(tr[x].n>1){tr[x].n--;update(x);return ;}
    if(tr[x].son[0]==0&&tr[x].son[1]==0){root=0;len=0;}
    else if(tr[x].son[0]==0&&tr[x].son[1]!=0){root=tr[x].son[1];tr[root].f=0;}
    else if(tr[x].son[0]!=0&&tr[x].son[1]==0){root=tr[x].son[0];tr[root].f=0;}
    else
    {
        int p=tr[x].son[0];
        while(tr[p].son[1]!=0) p=tr[p].son[1];
        splay(p,x);
        int r=tr[x].son[1],R=p;
        tr[R].son[1]=r;
        tr[r].f=R;
        root=R;tr[root].f=0;
        update(R);
    }
}
void findpaiming(int d)
{
    int x=findip(d);splay(x,0);
    printf("%d\n",tr[tr[x].son[0]].c+1);
}
void findshuzi(int k)
{
    int x=root;
    while(1)
    {
        int lc=tr[x].son[0],rc=tr[x].son[1];
        if(k<=tr[lc].c) x=lc;
        else if(k>tr[lc].c+tr[x].n) {k-=tr[lc].c+tr[x].n;x=rc;}
        else break;
    }
    splay(x,0);
    printf("%d\n",tr[x].d);
}
void findqianqu(int d)
{
    int x=findip(d);splay(x,0);
    if(d<=tr[x].d)
    {
        x=tr[x].son[0];
        while(tr[x].son[1]!=0) x=tr[x].son[1];
    }
    printf("%d\n",tr[x].d);
}
void findhouji(int d)
{
    int x=findip(d);splay(x,0);
    if(tr[x].d<=d)
    {
        x=tr[x].son[1];
        while(tr[x].son[0]!=0) x=tr[x].son[0];
    }
    printf("%d\n",tr[x].d);
}
int main()
{    
    int n;
    scanf("%d",&n);
    root=0;len=0;
    for(int i=1;i<=n;i++)
    {
        int cz,x;scanf("%d%d",&cz,&x);
        if(cz==1) ins(x);
        else if(cz==2) del(x);
        else if(cz==3) findpaiming(x);
        else if(cz==4) findshuzi(x);
        else if(cz==5) findqianqu(x);
        else if(cz==6) findhouji(x);
    }
    return 0;
}

 

posted @ 2018-02-08 09:53  Star_Feel  阅读(172)  评论(0编辑  收藏  举报