【treap模板】【TyvJ 1728】【普通平衡树】

3 篇文章 0 订阅
2 篇文章 0 订阅

这里写图片描述


Tyvj 1728 普通平衡树

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

Input

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

Output

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

Sample Input

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

Sample Output

106465
84185
492737

Hint

1.n的数据范围:n<=100000

2.每个数的数据范围:[-2e9,2e9]


在此总结一下自己容易犯下的错误:
【1】忘记在del函数,insert函数特判时加return
【2】忘记对a[](size)或w[](自己总数)进行操作
【3】忘记加if(v == 0 )的特判(特别是在q_n_r, q_l , q_r的时候)
【4】del时对于旋转操作后向下递归时时tow^1方向


代码如下:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 200001
#define mod (1 << 31) - 1
using namespace std;
int n;
int ch[M][2] , val[M] , ran[M] , a[M] , w[M] , tot , root;

inline int rand_(){
    static int seed = 233;
    return seed = int(seed * 48271LL % mod);
}

void maintain(int x){a[x] = w[x] + a[ch[x][0]] + a[ch[x][1]];}

void rotate(int &v , int tow){
    int son = ch[v][tow];
    ch[v][tow] = ch[son][tow ^ 1];
    ch[son][tow ^ 1] = v;
    maintain(v);maintain(son);
    v = son;
}

void insert(int &v , int val_){
    if(!v){
        val[v = ++tot] = val_;
        ran[v] = rand_();
        w[v] = a[v] = 1;
        return;
    }   
    ++a[v];
    if(val[v] == val_){++w[v];return;}
    int tow = val_ > val[v];
    insert(ch[v][tow] , val_);
    if(ran[v] > ran[ch[v][tow]])
        rotate(v , tow);
}

void del(int &v , int val_){
    if(!v)return; 
    if(val[v] == val_){
        if(w[v] > 1){--a[v] , --w[v];return;}
        if(ch[v][1] * ch[v][0] == 0){v = ch[v][1] + ch[v][0];return;}
        int tow = ran[ch[v][0]] > ran[ch[v][1]];
        rotate(v , tow);
        --a[v];
        del(ch[v][tow ^ 1] , val_);
        return;
    }
    --a[v];
    int tow = val[v] < val_;
    del(ch[v][tow] , val_);
}

int ans = 0;

void q_l(int v , int val_){
    if(!v)return;
    if(val_ > val[v]){ans = val[v];q_l(ch[v][1] , val_);return;}
    q_l(ch[v][0] , val_);
}

void q_r(int v , int val_){
    if(!v)return;
    if(val_ < val[v]){ans = val[v];q_r(ch[v][0] , val_);return;}
    q_r(ch[v][1] , val_);
}

int q_r_n(int v , int val_){
    if(!v)return -1;
    if(a[ch[v][0]] >= val_)return q_r_n(ch[v][0] , val_);
    if(a[ch[v][0]] + w[v] < val_)return q_r_n(ch[v][1] , val_ - a[ch[v][0]] - w[v]);
    return val[v];
}

int q_n_r(int v , int val_){
    if(!v)return 0;
    if(val_ > val[v])return q_n_r(ch[v][1] , val_) + w[v] + a[ch[v][0]];
    if(val_ < val[v])return q_n_r(ch[v][0] , val_);
    return a[ch[v][0]] + 1;
}

int main()
{
    scanf("%d",&n);
    int y,x;
    for(register int i=1;i<=n;i++)
    {   
        scanf("%d%d",&y,&x);
         switch(y)
        {
        case 1:insert(root,x);break;
        case 2:del(root,x);break;
        case 4:printf("%d\n",q_r_n(root,x));break;
        case 3:printf("%d\n",q_n_r(root,x));break;
        case 5:ans=0;q_l(root,x);printf("%d\n",ans);break;
        case 6:ans=0;q_r(root,x);printf("%d\n",ans);break;
        }
    }
    return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
红黑平衡二叉都是用于保持二叉搜索平衡的数据结构,但它们在某些方面有所不同。 优点: 1. 平衡性:红黑平衡二叉都能够在插入和删除操作后自动调整的结构,保持平衡,从而保证了在最坏情况下的查找效率为O(log n)。 2. 动态性:红黑平衡二叉都支持高效的动态插入和删除操作,适用于频繁更新的应用场景。 3. 操作简单:相比其他平衡结构,红黑平衡二叉的操作相对简单,实现起来较为容易。 差异: 1. 结构性:红黑是一种特殊的二叉搜索,它在每个节点上增加了一个额外的颜色属性,并通过一些规则来保持平衡。而平衡二叉是一种更广义的概念,可以有多种实现方式,如AVLTreap等。 2. 调整频率:红黑的调整操作相对较少,仅在插入和删除时需要进行调整。而平衡二叉可能需要更频繁地进行调整,因为它要保持每个节点的左右子高度差不超过1。 3. 空间利用:红黑需要额外的颜色属性来维持平衡,并且每个节点还需要存储其颜色信息。而平衡二叉只需要存储节点值和指向左右子的指针,相对而言空间利用更加紧凑。 综上所述,红黑相对于平衡二叉在实现和调整操作上更简单,但在空间利用上稍逊一筹。选择使用哪种结构取决于具体应用场景和需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值