普通平衡树

题意:略,题中较清晰。

用二叉查找树来存储数据,为了增加效率,尽量使左子树和右子树的深度差不超过一,这样可以时间控制在logn,效率比较高。

右旋和左旋,目的是为了维护二叉树的操作,使其尽量平衡。

int n, m;
int o[N];
struct Node { // 节点int l, r; // 左儿子,右儿子int key, val; // 数据值,随机值(用以维护二叉树尽量平衡的条件) int cnt, size; // 当前key值的数量,当前子树的所有节点的cnt值和
} tr[N];
int root, idx; // 根节点,下一个可以分配的节点序号void push_up(int p) { // 与线段树操作的意义一样tr[p].size = tr[tr[p].l].size + tr[tr[p].r].size + tr[p].cnt; // 左右子树的size和加上本身cnt
}int get_node(int key) { // 创建一个节点,返回节点序号tr[++ idx].key = key; // 初始化keytr[idx].val = rand(); // 随机一个01给valtr[idx].cnt = tr[idx].size = 1; // 数量为1,只有本身return idx; // 返回序号
}void build() { // 建立一个空的二叉树,只有两个哨兵,无穷大与无穷小get_node(-INF), get_node(INF);root = 1, tr[1].r = 2; push_up(root);
}void zig(int &p) { // 右旋int q = tr[p].l; // q为根节点左儿子tr[p].l = tr[q].r, tr[q].r = p, p = q; // 对应图片分析push_up(tr[p].r), push_up(p); // 更新size值
}void zag(int &p) { // 左旋int q = tr[p].r; // q为根节点右儿子tr[p].r = tr[q].l, tr[q].l = p, p = q; // 对应图片分析push_up(tr[p].l), push_up(p); // 更新size值
}void insert(int &p, int key) { // 插入一个节点keyif(!p) p = get_node(key); // 该key值未出现过,创建一个新的节点,并将序号返回到上一级else if(tr[p].key == key) tr[p].cnt ++; // 出现过,直接cnt数量加一else if(tr[p].key > key) { // 应该插在左儿子insert(tr[p].l, key); // 递归左儿子if(tr[tr[p].l].val > tr[p].val) zig(p); // 左儿子val值大于本身,右旋处理} else { // 应该插在右儿子insert(tr[p].r, key); // 递归右儿子if(tr[tr[p].r].val > tr[p].val) zag(p); // 右儿子var值大于本身,左旋处理}push_up(p); // 更新size状态return ;
}void remove(int &p, int key) { // 删除一个key值节点if(!p) return ; // 没找到,直接结束if(tr[p].key == key) { // 找到key值节点if(tr[p].cnt > 1) tr[p].cnt --; // 数量不唯一,直接减一即可else if(tr[p].l || tr[p].r) { // 数量唯一且存在儿子if(!tr[p].r || tr[tr[p].l].val > tr[tr[p].r].val) {// 右儿子存在或者左儿子var值大于右儿子,右旋处理zig(p);remove(tr[p].r, key);// 右旋之后key值节点交换到当前p节点的右儿子,遍历右儿子,一直递归直到没有儿子的时候删除} else {// 应该进行左旋处理zag(p);remove(tr[p].l, key);// 左旋之后key值节点交换到当前p节点的左儿子,遍历左儿子,一直递归直到没有儿子的时候删除}} else p = 0; // 数量唯一且没有儿子,直接删除即可。} else if(tr[p].key > key) remove(tr[p].l, key); // key值点在左儿子else remove(tr[p].r, key); // key值点在右儿子push_up(p);
}int get_rank_by_key(int p, int key) { // 根据key值找排名if(!p) return 1;  // 没找到直接return 1,因为洛谷这个题说的是不存在的数的排名为比它的数量加一if(tr[p].key == key) return tr[tr[p].l].size + 1; // 找到key值,返回key值在当前子树的排名if(tr[p].key > key) return get_rank_by_key(tr[p].l, key);// key在左子树return get_rank_by_key(tr[p].r, key) + tr[tr[p].l].size + tr[p].cnt; // key在右子树,因为左子树以及本身都是比它小的,所以需要加上这些数量,再去递归右子树,计算key值在右子树的排名
}
int get_key_by_rank(int p, int rank) {  // 找到排名为rank的key值if(!p) return INF; // 没找到,不存在这个排名的数if(tr[tr[p].l].size >= rank) return get_key_by_rank(tr[p].l, rank); // 在左子树if(tr[tr[p].l].size + tr[p].cnt >= rank) return tr[p].key; // 在本身return get_key_by_rank(tr[p].r, rank - tr[tr[p].l].size - tr[p].cnt); // 在右子树,需要减去左子树以及本身的数量	
}
int get_prev(int p, int key) { // 获得比key小的最大数if(!p) return -INF; // 没找到if(tr[p].key >= key) return get_prev(tr[p].l, key); // 在左子树return max(tr[p].key, get_prev(tr[p].r, key)); // 本身和右子树都比key小,都有可能,递归右子树与本身进行判断。
}
int get_next(int p, int key) { // 获得比key大的最小数if(!p) return INF; // 没找到if(tr[p].key <= key) return get_next(tr[p].r, key); // 在右子树return min(tr[p].key, get_next(tr[p].l, key));  // 本身和左子树都比key大,都有可能,递归左子树与本身进行判断。
}
inline void sovle() {build();
//	cout << idx << endl;cin >> n;while(n --) {int opt, x;cin >> opt >> x;if(opt == 1) insert(root, x);else if(opt == 2) remove(root, x);else if(opt == 3) cout << get_rank_by_key(root, x) - 1 << endl;else if(opt == 4) cout << get_key_by_rank(root, x + 1) << endl;else if(opt == 5) cout << get_prev(root, x) << endl;else cout << get_next(root, x) << endl;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/162893.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Dubbo引入Zookeeper等注册中心简介以及DubboAdmin简要介绍,为后续详解Dubbo各种注册中心做铺垫!

文章目录 一&#xff1a;Dubbo注册中心引言 1&#xff1a;什么是Dubbo的注册中心&#xff1f; 2&#xff1a;注册中心关系图解 3&#xff1a;引入注册中心服务执行流程 4&#xff1a;Dubbo注册中心好处 5&#xff1a;注册中心核心作用 二&#xff1a;注册中心实现方案 …

Springboot+vue的新冠病毒密接者跟踪系统(有报告)。Javaee项目,springboot vue前后端分离项目

演示视频&#xff1a; Springbootvue的新冠病毒密接者跟踪系统(有报告)。Javaee项目&#xff0c;springboot vue前后端分离项目 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的新冠病毒密接者跟踪系统&#xff0c;采用M&#xff08;model&#xff09;V&#xff08;v…

景区智慧旅游智能化系统方案:PPT全文58页,附下载

关键词&#xff1a;智慧景区解决方案&#xff0c;智慧文旅解决方案&#xff0c;智慧旅游解决方案&#xff0c;智慧文旅综合运营平台 一、景区智慧旅游智能化系统建设背景 近年来&#xff0c;随着信息技术的快速发展和普及&#xff0c;以及旅游市场的不断扩大和升级&#xff0…

电脑自动删除文件怎么办?如何恢复?

在数字化时代&#xff0c;电脑已经成为人们不可或缺的工具之一。然而&#xff0c;由于各种原因&#xff0c;我们有时会遇到电脑自动删除文件的情况&#xff0c;这给我们的工作和生活带来了很多不便。那么&#xff0c;当电脑自动删除文件时&#xff0c;我们应该如何处理呢&#…

【Python爬虫】8大模块md文档从0到scrapy高手,第8篇:反爬与反反爬和验证码处理

本文主要学习一下关于爬虫的相关前置知识和一些理论性的知识&#xff0c;通过本文我们能够知道什么是爬虫&#xff0c;都有那些分类&#xff0c;爬虫能干什么等&#xff0c;同时还会站在爬虫的角度复习一下http协议。 Python爬虫和Scrapy全套笔记直接地址&#xff1a; 请移步这…

数据结构与算法编程题14

设计一个算法&#xff0c;通过一趟遍历在单链表中确定值最大的结点。 #include <iostream> using namespace std;typedef int Elemtype; #define ERROR 0; #define OK 1;typedef struct LNode {Elemtype data; //结点保存的数据struct LNode* next; //结构体指针…

RedHat NTP时间服务器配置Chrony(所有节点时间跟主节点时间同步)

NTP NTP&#xff08;Network Time Protocol&#xff09;是一种用于在计算机网络中同步时钟的协议。它的主要目的是确保网络中的各个设备具有准确的时间参考&#xff0c;以便协调事件顺序、安全通信和日志记录等应用。它通过分层体系结构、时间同步算法和准确的时间参考源来确保…

Linux设置静态IP

Linux设置静态IP 使用ip addr查看ip&#xff0c;如下所示就是动态IP 1、什么是静态IP&#xff1f; 静态ip就是固定的ip&#xff0c;需要手动设置。静态IP地址&#xff08;又称固定IP地址&#xff09;是长期分配给一台计算机或网络设备使用的 IP 地址。一般来说&#xff0c;一…

738. Monotone Increasing Digits 968. Binary Tree Cameras

738. Monotone Increasing Digits An integer has monotone increasing digits单调递增数字 if and only if each pair of adjacent digits x and y satisfy x < y. Given an integer n, return the largest number that is less than or equal to n with monotone increa…

TypeScript 学习笔记 第三部分 贪吃蛇游戏

尚硅谷TypeScript教程&#xff08;李立超老师TS新课&#xff09; 1. 创建开发环境 创建工程&#xff0c;使用学习笔记的第二部分安装css部分 npm i -D less less-loader css-loader style-loader对css部分处理&#xff0c;能够运行在低版本浏览器 npm i -D postcss postcss…

音色逼真、韵律自然的AI人声克隆限时福利!

声音&#xff0c;为数字人注入灵魂。 2023云栖大会上&#xff0c;阿里云视频云接受了CCTV-2财经频道的采访&#xff0c;分享并演示了如何利用云端智能剪辑&#xff0c;一站式完成数字人渲染及视频精编二创。 正如视频开头所呈现的AI重现演员“原声”&#xff0c;近年来&#x…

基于SpringBoot的图书管理系统

基于SpringBoot的图书管理系统 图书管理系统开发技术功能模块代码结构数据库设计运行截图源码获取 图书管理系统 开发技术 技术&#xff1a;SpringBoot、MyBatis-Plus、MySQL、Beetl、Layui。 框架&#xff1a;基于开源框架Snowy-Layui开发。 工具&#xff1a;IDEA、Navicat等…

【Linux】进程间通信——进程间通信的介绍和分类、管道、匿名管道、命名管道、匿名管道与命名管道的区别

文章目录 进程间通信1.进程间通信的介绍1.1目的和发展 2.进程间通信分类3.管道3.1匿名管道3.1.1匿名管道的原理&#xff08;文件角度&#xff09;3.1.2匿名管道的原理&#xff08;内核角度&#xff09;3.1.3管道读写规则3.1.4管道特点 3.2命名管道3.2.1创建命名管道3.2.2命名管…

谈思生物医疗直播 | 利用类器官模型研究肺的发育与稳态

类器官是一种三维细胞培养物&#xff0c;其在细胞类型&#xff0c;空间结构及生理功能上能够模拟对应器官&#xff0c;从而提供一个高度生理相关的系统。自2009年小肠类器官首次建立至今&#xff0c;类器官研究已经延伸到多个组织系统&#xff0c;并成为当下生命科学领域最热门…

美创获IDC数据库安全市场代表厂商推荐,一路引领数据库安全

近日&#xff0c;全球领先的IT市场研究和咨询公司IDC发布《IDC Persepctive&#xff1a;中国数据库安全市场洞察&#xff0c;2023》报告。 凭借多年的技术积累和丰富的产品体系与行业实践&#xff0c;美创科技获「代表厂商」推荐&#xff0c;再次彰显专业领先能力&#xff01; …

Mybatis一级缓存和二级缓存原理剖析与源码详解

Mybatis一级缓存和二级缓存原理剖析与源码详解 在本篇文章中&#xff0c;将结合示例与源码&#xff0c;对MyBatis中的一级缓存和二级缓存进行说明。 MyBatis版本&#xff1a;3.5.2 文章目录 Mybatis一级缓存和二级缓存原理剖析与源码详解⼀级缓存场景一场景二⼀级缓存原理探究…

部署项目时常用的 Linux 命令

目录 1 前言2 SSH登录命令3 SCP传输命令4 CP拷贝命令5 MV移动命令6 TAR解压命令7 DU查看文件夹/文件大小8 TAIL查看日志9 NOHUP后台运行10 结语 1 前言 在应用部署过程中&#xff0c;Linux命令是必不可少的工具。它们能够帮助我们管理文件、连接服务器、拷贝文件、查看日志以及…

vite项目配置vite.config.ts在打包过程中去除日志

在生产环境上&#xff0c;务必要将日志清除干净&#xff0c;其因有二&#xff0c;在webgis系统中&#xff0c;有很多几何数据&#xff0c;体积大、数量多&#xff0c;很容易引起系统卡顿&#xff1b;清除log后&#xff0c;系统看着舒服&#xff0c;协同开发有很多无聊的日志&am…

一款非常优秀的项目管理工具:进度猫(推荐)

在项目管理中&#xff0c;一个好的工具可以极大地提高效率。 进度猫是一款非常优秀的项目管理工具。它具有非常强大的功能&#xff0c;可以帮助团队更好地管理项目进度。 通过可视化的方式&#xff0c;将项目进度、任务分配、需求变更等全面呈现给团队成员&#xff0c;让团队…

需求分析BSA法

&#x1f449;BSA法&#xff08;Basic–Satisfier–Attractor&#xff09;是对客户需求进行优先级划分的需求分析方法。该模型体现了需求满足度和客户满意度之间的非线性关系。BSA法将客户需求分为3种类型&#xff0c;分别是基本型需求、满意型需求和兴奋型需求。下面将对每种需…