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

    题目描述

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

    1. 插入x数

    2. 删除x数(若有多个相同的数,因只删除一个)

    3. 查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)

    4. 查询排名为x的数

    5. 求x的前驱(前驱定义为小于x,且最大的数)

    6. 求x的后继(后继定义为大于x,且最小的数)

    输入输出格式

    输入格式:

    第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号( 1 leq opt leq 61opt6 )

    输出格式:

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

    说明

    时空限制:1000ms,128M

    1.n的数据范围: n leq 100000n100000

    2.每个数的数据范围: [-{10}^7, {10}^7][107,107]

    来源:Tyvj1728 原名:普通平衡树

    在此鸣谢

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<ctime>
    using namespace std;
    
    const int N=1e6+5;
    const int INF=599518803;
    
    int n,opt,x;
    struct Node
    {
        Node *son[2];    //左右儿子
    //    int lson,rson; 
        int key;    //这个节点的输入的值 
        int key_cnt;    //这个值出现的次数 
        int heap_key;    //rand()的维护堆的性质的值 
        int size;    //这棵树的节点个数 
    }node[N],_null;
    
    typedef Node* Tree;
    Tree node_now,root,null;
    
    int read()
    {
        char c=getchar();int num=0,f=1;
        for(;!isdigit(c);c=getchar())
            if(c=='-')
                f=-1;
        for(;isdigit(c);c=getchar())
            num=num*10+c-'0';
        return num*f;
    }
    
    void init()
    {
        srand(time(NULL));
        node_now=node;
        root=null=&_null;
        null->heap_key=null->key=2147483647;
        null->son[0]=null->son[1]=null;
        null->size=0;
        null->key_cnt=0;
    }
    
    Tree newNode(int key)
    {
        ++node_now;
        node_now->key=key;
        node_now->key_cnt=1;
        node_now->heap_key=rand();
        node_now->size=1;
        node_now->son[0]=null;
        node_now->son[1]=null;
        return node_now;
    }
    
    void rotate(Tree &root,bool flag)
    {
        Tree tmp=root->son[!flag];
        root->son[!flag]=tmp->son[flag];
        tmp->son[flag]=root;
        root->size=root->son[0]->size+root->son[1]->size+root->key_cnt;
        tmp->size=tmp->son[0]->size+tmp->son[1]->size+tmp->key_cnt;
        root=tmp;
    }
    
    void insert(Tree &root,int key)
    {
        if(root==null)
            root=newNode(key);
        else if(root->key==key)
            ++root->key_cnt,++root->size;
        else
        {
        //printf("    %d
    ",root->key);
            ++root->size;
            bool flag=key>root->key;        //WA点1:把root->key写成了root->heap_key, 粗心! 
            insert(root->son[flag],key);
            if(root->heap_key<root->son[flag]->heap_key)
                rotate(root,!flag);
        }
    }
    
    void erase(Tree &root,int key)
    {
        if(root==null)
            return;
        if(root->key!=key)
        {
            bool flag=key>root->key;
            --root->size;
            erase(root->son[flag],key);
        }
        else
        {
            if(root->key_cnt>1)
                --root->key_cnt,
                --root->size;
            else if(root->son[0]==null)
                root=root->son[1];
            else if(root->son[1]==null)
                root=root->son[0];
            else
            {
                bool flag=root->son[0]->heap_key>root->son[1]->heap_key;
                rotate(root,flag);
                erase(root,key);
            }
        }
    }
    
    int query_rank(Tree root,int x)
    {
        if(root==null)
            return 0;
        if(root->key==x)
            return root->son[0]->size+1;
        bool flag=x>root->key;
        if(flag)
            return root->son[0]->size+root->key_cnt+query_rank(root->son[1],x);
        else
            return query_rank(root->son[0],x);
    }
    
    int query_num(Tree root,int k)
    {
        if(root==null)
            return 0;
        else if(k<=root->son[0]->size)
            return query_num(root->son[0],k);
        else if(k>root->son[0]->size+root->key_cnt)
            return query_num(root->son[1],k-root->son[0]->size-root->key_cnt);
        else
            return root->key;
    }
    
    int query_pre(Tree root,int x)
    {
        if(root==null)
            return -2147483646;
        else if(root->key<x)
            return max(root->key,query_pre(root->son[1],x));
        else
            return query_pre(root->son[0],x);
    }
    
    int query_nxt(Tree root,int x)
    {
        if(root==null)
            return 2147483647;
        //printf("%d
    ",root->key);
        else if(root->key>x)
            return min(root->key,query_nxt(root->son[0],x));
        else
            return query_nxt(root->son[1],x);
    }
    
    int main()
    {
        //freopen("233.in","r",stdin);
        //freopen("233.out","w",stdout);
        init();
        n=read();
        while(n--)
        {
            opt=read(),x=read();
            switch(opt)
            {
                case 1:
                    insert(root,x);break;
                case 2:
                    erase(root,x);break;
                case 3:
                    printf("%d
    ",query_rank(root,x));break;
                case 4:
                    printf("%d
    ",query_num(root,x));break;
                case 5:
                    printf("%d
    ",query_pre(root,x));break;
                default:
                    printf("%d
    ",query_nxt(root,x));
            }
        }
        return 0;
    }
  • 相关阅读:
    IntelliJ IDEA使用心得之问题篇;
    IntelliJ IDEA使用心得之Maven项目篇
    IntelliJ IDEA使用心得之非Maven项目篇
    IntelliJ IDEA使用心得之插件篇
    IntelliJ IDEA使用心得之快捷键篇
    新博客地址
    【转载】Dijkstra算法和Floyd算法的正确性证明
    【转载】最小生成树之Kruskal算法
    论自动AC机
    【转载】C++ STL priority_queue用法
  • 原文地址:https://www.cnblogs.com/lovewhy/p/8463546.html
Copyright © 2011-2022 走看看