zoukankan      html  css  js  c++  java
  • Luogu 3369 / BZOJ 3224

    题目链接:

    https://www.lydsy.com/JudgeOnline/problem.php?id=3224

    https://www.luogu.org/problemnew/show/P3369

    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]

    可能最近搞平衡二叉搜索树上瘾了?搞完替罪羊树再来搞搞无旋Treap。

    关于无旋Treap:

    我们已经知道了Treap是怎么写的:BZOJ 3224 - 普通平衡树 - [Treap][Splay]

    我们知道,普通的Treap是要zigzag的,而无旋Treap顾名思义就是不需要zigzag。

    无旋Treap最基本的(也是核心的)操作只有两种,一种 $Merge$,一种 $Split$。

      $Split(x,k,a,b)$ 拆分操作:按照一个判定值 $k$ 将一个Treap $x$ 拆成两个Treap $a,b$(左树和右树),满足左树的所有值均小于等于 $k$,右树的所有值都大于 $k$。

      $Merge(x,a,b)$ 合并操作:将两个Treap $a,b$ (满足 $a$ 中所有元素均小于 $b$ 中所有元素),合并成一个Treap $x$。合并的原则是节点的堆权值满足堆性质,所以是一种平衡树。

    另外,与普通Treap不同的是,每个节点均只存一个元素;也就是说,若存在若干个相同元素,会有若干个节点,而非一个节点用 $cnt$ 去记录。

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int INF=INT_MAX;
    const int maxn=1e5+10;
    
    /******************************** FHQ Treap - st ********************************/
    int root,nodecnt;
    int ch[maxn][2];
    int key[maxn],dat[maxn];
    int siz[maxn];
    int NewNode(int val)
    {
        int x=++nodecnt;
        key[x]=val, dat[x]=rand();
        siz[x]=1, ch[x][0]=ch[x][1]=0;
        return x;
    }
    void Pushup(int x) {
        siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
    }
    void Init()
    {
        root=nodecnt=0;
        key[0]=dat[0]=0;
        siz[0]=0, ch[0][0]=ch[0][1]=0;
    }
    void Split(int x,int k,int &a,int &b)
    {
        if(x==0)
        {
            a=b=0;
            return;
        }
        if(key[x]<=k) a=x, Split(ch[x][1],k,ch[a][1],b);
        else b=x, Split(ch[x][0],k,a,ch[b][0]);
        Pushup(x);
    }
    void Merge(int &x,int a,int b)
    {
        if(a==0 || b==0)
        {
            x=a+b;
            return;
        }
        if(dat[a]<dat[b]) x=a, Merge(ch[x][1],ch[a][1],b);
        else x=b, Merge(ch[x][0],a,ch[b][0]);
        Pushup(x);
    }
    
    int GetRank(int val)
    {
        int a=0,b=0;
        Split(root,val-1,a,b);
        int res=siz[a]+1;
        Merge(root,a,b);
        return res;
    }
    int GetKth(int x,int k)
    {
        if(x==0) return INF;
        if(siz[ch[x][0]]+1==k) return key[x];
        if(siz[ch[x][0]]>=k) return GetKth(ch[x][0],k);
        else return GetKth(ch[x][1],k-siz[ch[x][0]]-1);
    }
    void Insert(int val)
    {
        int a=0,b=0;
        Split(root,val,a,b);
        Merge(a,a,NewNode(val));
        Merge(root,a,b);
    }
    void Remove(int val)
    {
        int a=0,b=0,c=0;
        Split(root,val,a,b);
        Split(a,val-1,a,c);
        Merge(c,ch[c][0],ch[c][1]);
        Merge(a,a,c);
        Merge(root,a,b);
    }
    int GetPre(int val)
    {
        int a=0,b=0;
        Split(root,val-1,a,b);
        int res=GetKth(a,siz[a]);
        Merge(root,a,b);
        return res;
    }
    int GetNxt(int val)
    {
        int a=0,b=0;
        Split(root,val,a,b);
        int res=GetKth(b,1);
        Merge(root,a,b);
        return res;
    }
    /******************************** FHQ Treap - ed ********************************/
    
    int main()
    {
        int n,opt,x;
        scanf("%d",&n);
        Init();
        while(n--)
        {
            scanf("%d%d",&opt,&x);
            if(opt==1) Insert(x);
            if(opt==2) Remove(x);
            if(opt==3) printf("%d
    ",GetRank(x));
            if(opt==4) printf("%d
    ",GetKth(root,x));
            if(opt==5) printf("%d
    ",GetPre(x));
            if(opt==6) printf("%d
    ",GetNxt(x));
        }
    }

    无旋Treap真的太好写了啊!!!QAQ又好写又好懂!!!比替罪羊树好多了QAQ!!!

  • 相关阅读:
    UPD通信
    异常处理
    网络编程-套接字(socket)
    数据分析(一)
    爬虫存储库之mongodb数据库(四)
    爬虫请求库selenium(三)
    爬虫解析库beautifulsoup(二)
    爬虫简介与request库(一)
    flask框架数据库之SQLAlchemy
    flask框架(四)
  • 原文地址:https://www.cnblogs.com/dilthey/p/10076589.html
Copyright © 2011-2022 走看看