Bzoj P3224 [Tyvj1728]普通平衡树___Treap

3 篇文章 0 订阅

题目大意:

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

题解:

一道平衡树的模板题,我们可以用Treap实现
只需要在每个节点多添加一个域cnt记录该节点所对应的数出现的数量,以及以这颗点为根的子树的大小,就可以查询x数的排名和排名x的数
然后递归实现Treap就可以了

代码:

#include<bits/stdc++.h>
#define INF 0x7fffffff
#define N 100005

using namespace std;

struct Treap{
    int l,r;
    int val,dat;
    int cnt,size;
} a[N];
int tot,root,n;

int New(int val){
    a[++tot].val = val;
    a[tot].dat = rand();
    a[tot].cnt = a[tot].size = 1;
    return tot;
}

void Update(int p){
    a[p].size = a[a[p].l].size + a[a[p].r].size + a[p].cnt;
}

void Build(){
    New(-INF); New(INF);
    root = 1; 
    a[root].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) 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 GetRankByVal(int p,int val){
    if (!p) return 0;
    if (val == a[p].val) return a[a[p].l].size + 1;
    if (val < a[p].val) return GetRankByVal(a[p].l,val);
    return GetRankByVal(a[p].r,val) + a[a[p].l].size + a[p].cnt;
}

int GetValByRank(int p,int rank){
    if (!p) return INF;
    if (a[a[p].l].size >= rank) return GetValByRank(a[p].l,rank);
    if (a[a[p].l].size + a[p].cnt>=rank) return a[p].val;
    return GetValByRank(a[p].r,rank - a[a[p].l].size - 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);
    while (n--){
           int s,x;
           scanf("%d%d",&s,&x);
           if (s == 1) Insert(root,x);
           if (s == 2) Remove(root,x);
           if (s == 3) printf("%d\n",GetRankByVal(root,x) - 1);
           if (s == 4) printf("%d\n",GetValByRank(root,x+1));
           if (s == 5) printf("%d\n",GetPre(x));
           if (s == 6) printf("%d\n",GetNext(x));
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值