zoukankan      html  css  js  c++  java
  • 无旋Treap(P3369 【模板】普通平衡树)

    原题链接:https://www.luogu.com.cn/problem/P3369

    题意:

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

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

    思路:

    可以看讲解视频:https://www.bilibili.com/video/BV15b411H7Wg?t=185&p=2

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    #define ls(x) arr[x].child[0]
    #define rs(x) arr[x].child[1]
    const int N = 1e7+10;
    struct node{
        int child[2],size,value,key;
    }arr[N];
    int tot;
    inline void Push_Up(int index){
        arr[index].size=arr[ls(index)].size+arr[rs(index)].size+1;
    }
    
    inline void split(int root,int& x,int& y,int value){//理解时,我们可以把x当做是答案的第一个,y当做答案的第二个,这个函数的意义是:将以root为根的树按照value分为以x为根的树和以y为根的树。注意引用的作用
        if(!root){
            x=y=0;//分到底了,返回
            return;
        }
        if(arr[root].value<=value){//如果比它小
            x=root;//那么value肯定在root的右子树里,先将root贴到第一个答案上
            split(rs(root),rs(x),y,value);//把第一个答案的右子树按value分开,得到答案(这里自己理解一下,不难懂)
        }else{//反之亦然
            y=root;
            split(ls(root),x,ls(y),value);
        }
        Push_Up(root);
    }
    
    inline void split1(int root,int& x,int& y,int value){
        if(!root){
            x=y=0;
            return;
        }
        if(arr[ls(root)].size+1<=value){
            x=root;
            split(rs(x),rs(x),y,value-arr[ls(root)].size-1);//注意这里有些变化 
        }else{
            y=root;
            split(ls(y),x,ls(y),value);
        }
        Push_Up(root);
    }
    
    inline void merge(int& root,int x,int y){//函数名的意义是:把以x为根的树和以y为根的树合并为以root为根的树 
        if(!x||!y){//合并到底,返回 
            root=x+y;
            return;
        }
        if(arr[x].key<arr[y].key){//默认大根堆 
            root=x;//先把x挂到root上 
            merge(rs(root),rs(x),y);//注意要满足BST性质
        }else{//反之亦然 
            root=y;
            merge(ls(root),x,ls(y));
        }
        Push_Up(root);
    }
    
    inline void insert(int& root, int value){
        int x=0,y=0,z=++tot;
        arr[z].value=value,arr[z].size=1,arr[z].key=rand();
        split(root,x,y,value);
        merge(x,x,z);
        merge(root,x,y);
    }
    inline void erase(int& root, int value){
        int x=0,y=0,z=0;
        split(root,x,y,value);
        split(x,x,z,value-1);
        merge(z,ls(z),rs(z));
        merge(x,x,z);
        merge(root,x,y);
    }
    inline int kth_number(int root, int k){
        while(arr[ls(root)].size+1!=k){
            if(arr[ls(root)].size>=k){
                root=ls(root);
            }else{
                k-=(arr[ls(root)].size+1);
                root=rs(root);
            }
        }
        return arr[root].value;
    }
    inline int get_rank(int& root,int value){
        int x=0,y=0;
        split(root,x,y,value-1);
        int res=arr[x].size+1;
        merge(root,x,y);
        return res;
    }
    inline int pre(int& root, int value){
        int x=0,y=0;
        split(root,x,y,value-1);    
        int res=kth_number(x,arr[x].size);
        merge(root,x,y);
        return res;
    }
    inline int suf(int& root, int value){
        int x=0,y=0;
        split(root,x,y,value);
        int res=kth_number(y,1);
        merge(root,x,y);
        return res;
    }
    int t,op,root;
    int main(){
        srand(time(0));
        cin>>t;
        while(t--){
            int x;
            cin>>op>>x;
            if(op==1){
                insert(root,x);
            }else if(op==2){
                erase(root,x);
            }else if(op==3){
                cout<<get_rank(root,x)<<endl;
            }else if(op==4){
                cout<<kth_number(root,x)<<endl;
            }else if(op==5){
                cout<<pre(root,x)<<endl;
            }else{
                cout<<suf(root,x)<<endl;
            }
        }
        return 0;
    }
  • 相关阅读:
    leetcode Power of Two
    leetcode Merge Two Sorted Lists
    Mac linux 安装memcached服务 用法
    Vsftp配置都没有问题 连接不上 530 Login incorrect 解决方法
    mysql 远程连接不上 %用户已经添加了
    Centos yum 安装mysql报错 No package mysql-server available.
    Linux 查询程序安装路径 是否安装
    php报错 Call to undefined function mb_stripos()
    mac编译openssl扩展报错 openssl.c:44:10: fatal error: 'openssl/evp.h' file not found
    在安装mysqli的时候,出现error: ext/mysqlnd/mysql_float_to_double.h: No such file or direc
  • 原文地址:https://www.cnblogs.com/shmilky/p/14095001.html
Copyright © 2011-2022 走看看