zoukankan      html  css  js  c++  java
  • bzoj 3224/Tyvj 1728 普通平衡树(splay)

    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

    Sample Output

    106465

    84185

    492737

    HINT

    1.n的数据范围:n<=100000

    2.每个数的数据范围:[-2e9,2e9]

    题解:平衡树裸题,我立志挖个写splay详解博客的坑,鬼知道省选之后会不会退役,反正难填

    代码如下:

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define N 500010
    using namespace std;
    
    struct Splay
    {
        int son[N][2],fa[N],key[N],cnt[N],size[N],rt,sz,pos;
        inline void push(int x)
        {
            size[x]=size[son[x][0]]+size[son[x][1]]+cnt[x];
        }
        inline void rotate(int x)
        {
            int y=fa[x],z=fa[y],k=(son[y][0]==x);
            son[z][son[z][1]==y]=x;
            fa[x]=z;
            son[y][!k]=son[x][k];
            fa[son[x][k]]=y;
            son[x][k]=y;
            fa[y]=x;
            push(y);
        }
        inline void splay(int x,int goal)
        {
            for(;fa[x]!=goal;rotate(x))
            {
                int y=fa[x],z=fa[y];
                if(z!=goal)
                {
                    (son[y][0]==x)^(son[z][0]==y)?rotate(x):rotate(y);
                }
            }
            push(x);
            if(!goal)
            {
                rt=x;
            }
        }
        inline void find(int x)
        {
            for(pos=rt;son[pos][x>key[pos]]&&x!=key[pos];pos=son[pos][x>key[pos]]);
            splay(pos,0);
        }
        inline void get(int x,int k)
        {
            find(x);
            if(!(key[pos]>x&&k||key[pos]<x&&!k))
            {
                for(pos=son[pos][k];son[pos][!k];pos=son[pos][!k]);
            }
        }
        inline void insert(int x)
        {
            int father=0;
            for(pos=rt;pos&&key[pos]!=x;pos=son[pos][x>key[pos]])
            {
                father=pos;
            }
            if(pos)
            {
                ++cnt[pos];
            }
            else
            {
                pos=++sz;
                son[father][x>key[father]]=pos;
                son[pos][0]=son[pos][1]=0;
                fa[pos]=father;
                key[pos]=x;
                cnt[pos]=size[pos]=1;
            }
            splay(pos,0);
        }
        inline void del(int x)
        {
            get(x,0);
            int pre=pos;
            get(x,1);
            int next=pos;
            splay(pre,0);
            splay(next,pre);
            pos=son[next][0];
            if(cnt[pos]>1)
            {
                --cnt[pos];
                --size[pos];
            }
            else
            {
                son[next][0]=0;
            }
            push(next);
            push(pre);
        }
        inline void kth(int k)
        {
            for(pos=rt;;)
            {
                int y=son[pos][0];
                if(k>size[y]+cnt[pos])
                {
                    k-=size[y]+cnt[pos];
                    pos=son[pos][1];
                }
                else
                {
                    if(size[y]<k)
                    {
                        return;
                    }
                    else
                    {
                        pos=y;
                    }
                }
            }
        }
        inline void put_key()
        {
            printf("%d
    ",key[pos]);
        }
    }splay1;
    
    int main()
    {
        int n,kd,val;
        splay1.insert(-1e9);
        splay1.insert(1e9);
        scanf("%d",&n);
        while(n--)
        {
            scanf("%d%d",&kd,&val);
            int x;
            switch(kd)
            {
                case 1:splay1.insert(val);
                       break;
                case 2:splay1.del(val);
                       break;
                case 3:splay1.find(val);
                       x=splay1.size[splay1.son[splay1.pos][0]];
                       printf("%d
    ",x);
                       break;
                case 4:splay1.kth(val+1);
                       splay1.put_key();
                       break;
                case 5:splay1.get(val,0);
                       splay1.put_key();
                       break;
                case 6:splay1.get(val,1);
                       splay1.put_key();
                       break;
            }
        }
    }
  • 相关阅读:
    用CSS开启硬件加速来提高网站性能
    vim中替换内容
    alias vi=vim
    PHP 多进程初识
    端口的查看
    PHP三种终止脚本执行:return,die,exit
    2021.3.14(每周总结)
    2021.3.13
    2021.3.12
    2021.3.11
  • 原文地址:https://www.cnblogs.com/stxy-ferryman/p/8530394.html
Copyright © 2011-2022 走看看