zoukankan      html  css  js  c++  java
  • 普通平衡树

    题目描述

    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
    1.插入x数
    2.删除x数(若有多个相同的数,因只删除一个)
    3.查询x数的排名(若有多个相同的数,因输出最小的排名)
    4.查询排名为x的数
    5.求x的前驱(前驱定义为小于x,且最大的数)
    6.求x的后继(后继定义为大于x,且最小的数)

    输入

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

    输出

    对于操作3,4,5,6每行输出一个数,表示对应答案

    样例输入

    10
    1 106465
    4 1
    1 317721
    1 460929
    1 644985
    1 84185
    1 89851
    6 81968
    1 492737
    5 493598

    样例输出

    106465
    84185
    492737

    提示

    1.n的数据范围:n<=100000
    2.每个数的数据范围:[-2e9,2e9]

    存个Treap的板子qwq
    #include<bits/stdc++.h>
    #define inf 0x7fffffff
    using namespace std;
    const int N=1e5+10;
    struct Treap{
        int l,r;
        int val,dat;
        int cnt,si;}a[N];
    int tot,root,n;
    
    void Update(int p)
    {
        a[p].si=a[a[p].l].si+a[a[p].r].si+a[p].cnt;
    }
    int New(int val)
    {
        a[++tot].val=val;
        a[tot].dat=rand();
        a[tot].cnt=a[tot].si=1;
        return tot;
    }
    void build()
    {
        New(-inf); New(inf);
        root=1; a[1].r=2;
        Update(root);
    }
    void zig(int &p)
    {
        int q=a[p].l;
        a[p].l=a[q].r; a[q].r=p; p=q;
        Update(a[p].r); Update(p);
    }
    void zag(int &p)
    {
        int q=a[p].r;
        a[p].r=a[q].l; a[q].l=p; p=q;
        Update(a[p].l); Update(p);
    }
    void Insert(int &p,int val)
    {
        if (p==0)
        {
            p=New(val);
            return ;
        }
        if (val==a[p].val)
        {
            a[p].cnt++; Update(p);
            return;
        }
        if (val<a[p].val)
        {
            Insert(a[p].l,val);
            if (a[p].dat<a[a[p].l].dat) zig(p);
        }
        else
        {
            Insert(a[p].r,val);
            if (a[p].dat<a[a[p].r].dat) zag(p);
        }
        Update(p);
    }
    
    void Remove(int &p,int val)
    {
        if (p==0) return ;
        if (val==a[p].val)
        {
            if (a[p].cnt>1) {a[p].cnt--; Update(p); return ;}
    
            if (a[p].l||a[p].r)
            {
                if (a[p].r==0 || a[a[p].l].dat>a[a[p].r].dat)
                    {zig(p); Remove(a[p].r,val);}
                else {zag(p); Remove(a[p].l,val);}
                Update(p);
            }
            else p=0;
            return ;
        }
        val < a[p].val ? Remove(a[p].l,val) : Remove(a[p].r,val);
        Update(p);
    }
    
    int GetRank(int p,int val)
    {
        if (p==0) return 0;
        if (val==a[p].val) return a[a[p].l].si+1;
        if (val<a[p].val) return GetRank(a[p].l,val);
        return GetRank(a[p].r,val)+a[a[p].l].si+a[p].cnt;
    }
    int GetVal(int p,int Rank)
    {
        if (p==0) return inf;
        if (a[a[p].l].si>=Rank) return GetVal(a[p].l,Rank);
        if (a[a[p].l].si+a[p].cnt>=Rank) return a[p].val;
        return GetVal(a[p].r,Rank-a[a[p].l].si-a[p].cnt);
    }
    
    int GetPre(int val)
    {
        int ans=1;
        int p=root;
        while (p)
        {
            if (val==a[p].val)
            {
                if (a[p].l>0)
                {
                    p=a[p].l;
                    while (a[p].r>0) p=a[p].r;
                    ans=p;
                }
                break;
            }
            if (a[p].val<val && a[p].val>a[ans].val) ans=p;
            p=val < a[p].val ? a[p].l : a[p].r;
        }
        return a[ans].val;
    }
    int GetNext(int val)
    {
        int ans=2;
        int p=root;
        while (p)
        {
            if (val==a[p].val)
            {
                if (a[p].r>0)
                {
                    p=a[p].r;
                    while (a[p].l>0) p=a[p].l;
                    ans=p;
                }
                break;
            }
            if (a[p].val>val && a[p].val<a[ans].val) ans=p;
            p=val < a[p].val ? a[p].l : a[p].r;
        }
        return a[ans].val;
    }
    int main()
    {
        build();
        scanf("%d",&n);
        int op,x;
        while (n--)
        {
            scanf("%d%d",&op,&x);
            if (op==1) Insert(root,x);
            else if (op==2) Remove(root,x);
            else if (op==3) printf("%d
    ",GetRank(root,x)-1);
            else if (op==4) printf("%d
    ",GetVal(root,x+1));
            else if (op==5) printf("%d
    ",GetPre(x));
            else printf("%d
    ",GetNext(x));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    字符串形式导入模块
    pycharm 远程环境开发调试
    ubuntu 18.04 及初始化python3环境
    nbu备份虚拟机
    转载
    linux/centos/rhel同时安装oracle10g和11g
    多进程
    drf笔记
    单例模式
    常用模块
  • 原文地址:https://www.cnblogs.com/tetew/p/9846090.html
Copyright © 2011-2022 走看看