• 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
    ",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
    ",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
    ",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
    ",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;
    }

     

  • 相关阅读:
    1
    Dockerfile概述
    协议
    部署环境
    协议与数据2
    【笔记】刚到公司,初识dll
    C#Winform学习笔记
    VS2019添加VisionPro控件(此方法是大师分享的)
    VisionPro脚本
    Visionpro相机取像操作,.NET4.0
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8430184.html
Copyright © 2020-2023  润新知