Gracekite's Homepage

Back

题目描述#

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

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

输入格式#

第一行为 ,表示操作的个数,下面 行每行有两个数 和 , 表示操作的序号( )

输出格式#

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

样例 #1#

样例输入 #1#

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

样例输出 #1#

106465
84185
492737
plaintext

数据范围#

对于 的数据,,

分析#

平衡树可以做什么#

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

算法分析#

旋转树(平衡树核心)#

void pushup(int pos){
    tree[pos].size=tree[tree[pos].s[0]].size+tree[tree[pos].s[1]].size+tree[pos].cnt; //合并当前节点数据
}
void rotate(int pos){
    int fa=tree[pos].fa,grandfa=tree[fa].fa; //父节点,父亲的父亲节点
    int fich = tree[fa].s[1]==pos;
    tree[fa].s[fich]=tree[pos].s[fich^1];
    tree[tree[pos].s[fich^1]].fa=fa;
    tree[pos].s[fich^1]=fa;
    tree[fa].fa=pos;
    tree[grandfa].s[tree[grandfa].s[1]==fa]=pos;
    tree[pos].fa=grandfa;
    pushup(fa),pushup(pos);
}
cpp

插入#

void insert(int val){
    int pos=root,fa=0; //从根开始
    while(pos&&tree[pos].val!=val) fa=pos,pos=tree[pos].s[val>tree[pos].val]; //根据BIT性质寻找离val最接近的值
    if(pos)tree[pos].cnt++; //如果已经存在当前值的点,直接将次数加1
    else{ //如果没有
        pos=++idx; //新建点
        tree[fa].s[val>tree[fa].val]=pos; //根据BIT性质选择插入位置
        tree[pos].init(fa,val); //初始化
    }
    splay(pos,0); //为方便后续操作,将当前节点设为根
}
cpp

BalanceTree平衡树
https://betteroier.github.io/blog/balancetree%E5%B9%B3%E8%A1%A1%E6%A0%91
Author Yuxuan Zheng
Published at November 20, 2022