zoukankan      html  css  js  c++  java
  • 洛谷p3369 treap

    这是一个treap裸题,还可以用splay,替罪羊树,线段树等等写

    treap是树和堆结合,可以方便的在O(log(n))期望时间内进行以下操作,因此treap又叫做名次树

    1. 插入x数

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

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

    4. 查询排名为x的数

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

    6. 求x的后继(后继定义为大于x,且最小的数)
    #include<bits/stdc++.h>
    #include<ext/rope>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define pii pair<int,int>
    #define C 0.5772156649
    #define pi acos(-1.0)
    #define ll long long
    #define mod 1000000007
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    
    using namespace std;
    using namespace __gnu_cxx;
    
    const double g=10.0,eps=1e-7;
    const int N=200000+10,maxn=100000+10,inf=0x3f3f3f;
    
    struct Node{
        Node* ch[2];
        int r;//排名
        int v;//权值
        int s;//节点数
        int flag;
        Node()
        {
            ch[0]=ch[1]=NULL;
            r=rand();v=0;
            s=flag=1;
        }
    };
    Node *root;
    void maintain(Node* &o)//更新当前结点子树的节点数
    {
        o->s=o->flag;
        if(o->ch[0]!=NULL)o->s+=o->ch[0]->s;//左子树不为空就加上数量
        if(o->ch[1]!=NULL)o->s+=o->ch[1]->s;//右子树不为空就加上数量
    }
    void Rotate(Node* &o,int d)//d=0左旋,d=1右旋
    {
        Node* k=o->ch[d^1];
        o->ch[d^1]=k->ch[d];
        k->ch[d]=o;
        maintain(o);maintain(k);
        o=k;
    }
    void Insert(Node* &o,int d)
    {
        if(o==NULL)//子树为空直接加上去
        {
            o=new Node;
            o->v=d;
            return ;
        }
        else if(o->v==d)//可能会相等
        {
            o->flag++;
            maintain(o);
            return ;
        }
        int d1=d>o->v ? 1:0;//判断搜索哪一颗子树
        Insert(o->ch[d1],d);
        if(o->ch[d1]->r > o->r)Rotate(o,d1^1);
        else maintain(o);
    }
    void Remove(Node* &o,int d)
    {
        if(o==NULL)return ;
        if(o->v==d)
        {
            if(o->flag>1)o->flag--;//该节点有多个数
            else
            {
                if(o->ch[0]==NULL&&o->ch[1]==NULL)o=NULL;
                else if(o->ch[0]!=NULL&&o->ch[1]!=NULL)
                {
                    if(o->ch[0]->r > o->ch[1]->r)Rotate(o,1),Remove(o->ch[1],d);
                    else Rotate(o,0),Remove(o->ch[0],d);
                }
                else //有一个节点不为空,就拿另一个补上
                {
                    if(o->ch[0]==NULL)o=o->ch[1];
                    else o=o->ch[0];
                }
            }
            if(o!=NULL)maintain(o);
        }
        else //根据d的大小找左右子树
        {
            if(d < o->v)Remove(o->ch[0],d);
            else if(d > o->v)Remove(o->ch[1],d);
            if(o!=NULL)maintain(o);
        }
    }
    int kth(Node* o,int k)//查询排名为k的节点
    {
        if(k<0||k > o->s||o==NULL)return 0;//不合法的情况
        int ss=0;//左子树的节点
        if(o->ch[0]!=NULL)ss=o->ch[0]->s;
        if(k>=ss+1&&k<=o->flag+ss)return o->v;
        if(ss>=k)return kth(o->ch[0],k);//左边够大了,从左边找
        else return kth(o->ch[1],k-ss-o->flag);
    }
    int Rank(Node* o,int k)//查询k的排名
    {
        if(o==NULL)return 0;
        int ss=0;
        if(o->ch[0]!=NULL)ss=o->ch[0]->s;
        if(o->v==k)return ss+1;
        if(o->v > k)return Rank(o->ch[0],k);//向左搜
        else return ss+o->flag+Rank(o->ch[1],k);//加上左子树的节点
    }
    void qq(Node* o,int k,int &ans)
    {
        if(o==NULL)return ;
        if(o->v < k)
        {
            ans=max(ans,o->v);
            if(o->ch[1]!=NULL)qq(o->ch[1],k,ans);
        }
        else
        {
            if(o->ch[0]!=NULL)qq(o->ch[0],k,ans);
        }
    }
    void hj(Node* o,int k,int &ans)
    {
        if(o==NULL)return ;
        if(o->v > k)
        {
            ans=min(ans,o->v);
            if(o->ch[0]!=NULL)hj(o->ch[0],k,ans);
        }
        else
        {
            if(o->ch[1]!=NULL)hj(o->ch[1],k,ans);
        }
    }
    int main()
    {
        srand(time(NULL));
        int n;
        cin>>n;
        while(n--)
        {
            int a,b;
            cin>>a>>b;  
            if(a==1)Insert(root,b);
            else if(a==2)Remove(root,b);
            else if(a==3)printf("%d
    ",Rank(root,b));
            else if(a==4)printf("%d
    ",kth(root,b));
            else if(a==5)
            {
                int ans=0;qq(root,b,ans);
                printf("%d
    ",ans);
            }
            else
            {
                int ans=1e9;hj(root,b,ans);
                printf("%d
    ",ans);
            }
        }
        return 0;
    }
    /*******************
    
    ********************/
    View Code
  • 相关阅读:
    Apache ServiceComb Pack 微服务分布式数据最终一致性解决方案
    EF core 性能调优
    Entity Framework Core Query Types
    Using the Repository and Unit Of Work Pattern in .net core
    CENTOS 7 下安装 REDIS 5.0.6 完整步骤
    MySQL InnoDB 群集–在Windows上设置InnoDB群集
    RFM客户价值分类
    修改meta标签
    $.Deferred 使用 (支持jQuery1.5版本以上)
    error: Unexpected console statement (no-console) 解决办法
  • 原文地址:https://www.cnblogs.com/acjiumeng/p/7732772.html
Copyright © 2011-2022 走看看