• 洛谷P3369 平衡树Treap


    题目描述

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

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

    输入格式

    第一行为 nn,表示操作的个数,下面 nn 行每行有两个数  ext{opt}opt 和 xx, ext{opt}opt 表示操作的序号( 1 leq ext{opt} leq 61opt6 )

    输出格式

    对于操作 3,4,5,63,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

    说明/提示

    【数据范围】
    对于 100\%100% 的数据,1le n le 10^51n105,|x| le 10^7x107

    //https://www.luogu.com.cn/problem/P3369
    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn=1e5+5;
    const int inf=0x3f3f3f3f;
    
    int sum ,R;
    int size[maxn],v[maxn],num[maxn],rd[maxn],son[maxn][2];
    
    void push_up(int p)
    {
        size[p]=size[son[p][0]]+size[son[p][1]]+num[p];
    }
    
    void rotate(int &p,int d)
    {
        int k=son[p][d^1];
        son[p][d^1]=son[k][d];
        son[k][d]=p;
        push_up(p);
        push_up(k);
        p=k;
    }
    
    void ins(int &p,int x)
    {
        if (!p)
        {
            p=++sum;
            size[p]=num[p]=1;
            v[p]=x;
            rd[p]=rand();
            return;
        }
        if (v[p]==x)
        {
            num[p]++;
            size[p]++;
            return;
        }
        int d=(x>v[p]);
        ins(son[p][d],x);
        if (rd[p]<rd[son[p][d]]) rotate(p,d^1);
        push_up(p);
    }
    
    void del(int &p,int x)
    {
        if (!p) return;
        if (x<v[p]) del(son[p][0],x);
        else if (x>v[p]) del(son[p][1],x);
        else
        {
            if (!son[p][0] && !son[p][1])
            {
                num[p]--; size[p]--; 
                if (num[p]==0) p=0;
            } 
            else if (son[p][0] && !son[p][1])
            {
                rotate(p,1);
                del(son[p][1],x);
            }
            else if (!son[p][0] && son[p][1])
            {
                rotate(p,0);
                del(son[p][0],x);
            }
            else if (son[p][0] && son[p][1])
            {
                int d=(rd[son[p][0]]>rd[son[p][1]]);
                rotate(p,d);
                del(son[p][d],x);
            }
        }
        push_up(p);
    }
    
    int rnk(int p,int x)
    {
        if (!p) return 0;
        if (v[p]==x) return size[son[p][0]]+1;
        if (v[p]<x) return size[son[p][0]]+num[p]+rnk(son[p][1],x);
        if (v[p]>x) return rnk(son[p][0],x);
    }
    
    int find(int p,int x)
    {
        if (!p) return 0;
        if (size[son[p][0]]>=x) return find(son[p][0],x);
        else if (size[son[p][0]]+num[p]<x)
            return find(son[p][1],x-num[p]-size[son[p][0]]);
        else return v[p];
    }
    
    int pre(int p,int x)
    {
        if (!p) return -inf;
        if (v[p]>=x) return pre(son[p][0],x);
        else return max(v[p],pre(son[p][1],x));
    }
    
    int suc(int p,int x)
    {
        if (!p) return inf;
        if (v[p]<=x) return suc(son[p][1],x);
        else return min(v[p],suc(son[p][0],x));
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            int opt,x;
            scanf("%d%d",&opt,&x);
            if (opt==1) ins(R,x);
            else if (opt==2) del(R,x);
            else if (opt==3) printf("%d
    ",rnk(R,x));
            else if (opt==4) printf("%d
    ",find(R,x));
            else if (opt==5) printf("%d
    ",pre(R,x));
            else if (opt==6) printf("%d
    ",suc(R,x));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    python删除列表重复元素
    maven常用打包命令
    python开发之函数
    手把手教你用Strace诊断问题
    python引用列表--10
    Python中open函数怎么操作文件--9
    python数据操作--8
    图解源码之FutureTask篇(AQS应用)
    图解源码之java锁的获取和释放(AQS)篇
    图解线程池工作机制,手写线程池?
  • 原文地址:https://www.cnblogs.com/Yokel062/p/13083569.html
Copyright © 2020-2023  润新知