当前位置: 首页 > news >正文

洛谷P5076 【深基16.例7】普通二叉树(简化版)

题目描述

您需要写一种数据结构,来维护一些数(都是绝对值 109 以内的数)的集合,最开始时集合是空的。其中需要提供以下操作,操作次数 q 不超过 104:

  1. 定义数 x 的排名为集合中小于 x 的数的个数 +1。查询数 x 的排名。注意 x 不一定在集合里
  2. 查询排名为 x(x≥1) 的数。保证集合里至少有 x 个数
  3. 求 x 的前驱(前驱定义为小于 x,且最大的数)。若不存在则输出 −2147483647。
  4. 求 x 的后继(后继定义为大于 x,且最小的数)。若不存在则输出 2147483647。
  5. 插入一个数 x,本题的数据保证插入前 x 不在集合中。

保证执行 1,3,4 操作时,集合中有至少一个元素。

输入格式

第一行是一个整数 q,表示操作次数。

接下来 q 行,每行两个整数 op,x,分别表示操作序号以及操作的参数 x。

输出格式

输出有若干行。对于操作 1,2,3,4,输出一个整数,表示该操作的结果。

输入输出样例

输入

7 5 1 5 3 5 5 1 3 2 2 3 3 4 3

输出

2 3 1 5
#include <bits/stdc++.h> using namespace std; // Treap 节点结构 struct Node { int val; // 节点值 int pri; // 随机优先级 int size; // 子树大小 Node *left, *right; Node(int v) : val(v), pri(rand()), size(1), left(nullptr), right(nullptr) {} }; // 获取子树大小,处理空指针 int getSize(Node *p) { return p ? p->size : 0; } // 更新节点 size void update(Node *p) { if (p) { p->size = 1 + getSize(p->left) + getSize(p->right); } } // 右旋 void rotateR(Node* &p) { Node *q = p->left; p->left = q->right; q->right = p; update(p); update(q); p = q; } // 左旋 void rotateL(Node* &p) { Node *q = p->right; p->right = q->left; q->left = p; update(p); update(q); p = q; } // 插入节点(递归) void insert(Node* &p, int x) { if (!p) { p = new Node(x); return; } if (x < p->val) { insert(p->left, x); if (p->left->pri < p->pri) rotateR(p); // 维护堆性质 } else { insert(p->right, x); if (p->right->pri < p->pri) rotateL(p); } update(p); } // 查询 x 的排名(小于 x 的个数 + 1) int getRank(Node *p, int x) { if (!p) return 1; // 空树返回1(实际不会发生,但递归边界) if (x <= p->val) return getRank(p->left, x); else return getSize(p->left) + 1 + getRank(p->right, x); } // 查询排名为 k 的数(第 k 小) int kth(Node *p, int k) { int leftSize = getSize(p->left); if (k <= leftSize) return kth(p->left, k); else if (k == leftSize + 1) return p->val; else return kth(p->right, k - leftSize - 1); } // 求 x 的前驱(小于 x 的最大数) int predecessor(Node *p, int x) { if (!p) return -2147483647; if (p->val >= x) return predecessor(p->left, x); else { int rightRes = predecessor(p->right, x); if (rightRes == -2147483647) return p->val; else return rightRes; } } // 求 x 的后继(大于 x 的最小数) int successor(Node *p, int x) { if (!p) return 2147483647; if (p->val <= x) return successor(p->right, x); else { int leftRes = successor(p->left, x); if (leftRes == 2147483647) return p->val; else return leftRes; } } int main() { srand(time(0)); // 初始化随机种子 int q; cin >> q; Node *root = nullptr; // 根节点初始化为空 while (q--) { int op, x; cin >> op >> x; switch (op) { case 1: // 查询排名 cout << getRank(root, x) << endl; break; case 2: // 查询第 k 小的数 cout << kth(root, x) << endl; break; case 3: // 前驱 cout << predecessor(root, x) << endl; break; case 4: // 后继 cout << successor(root, x) << endl; break; case 5: // 插入 insert(root, x); break; default: break; } } return 0; }
http://www.cnnetsun.cn/news/1361869.html

相关文章:

  • NX(UG)转 GLTF 格式完整教程:3种方案(推荐迪威模型网在线转换)
  • Qwen3-ForcedAligner-0.6B大模型在语音合成后处理中的应用
  • 避坑指南:Vue3+dataV大屏开发那些坑(从安装到团队协作全流程)
  • 5分钟搞定AI配音:用GPT-SoVITS把你的文字变成自己的声音(Windows版)
  • IntelliJ IDEA高效开发:从入门到精通的实战指南
  • GME多模态向量-Qwen2-VL-2B实战教程:为LLM提供多模态上下文增强的RAG集成方案
  • 如何用开源工具实现窗口放大?让低分辨率内容焕发高清质感
  • Gaussian 计算服务器硬件选型与性能优化指南
  • Flutter开发者的宝藏清单:2023年最值得关注的10个第三方库(附实战代码)
  • 电力电子新手必看:电压型与电流型逆变电路的区别与选型指南
  • 破大防!日本最大高性能“乐天AI3.0”被扒出基于DeepSeekV3架构
  • ANOMALYCLIP: OBJECT-AGNOSTIC PROMPT LEARN-ING FOR ZERO-SHOT ANOMALY DETECTION
  • M2LOrder企业级应用案例:呼叫中心语音转文本后情感打标实战
  • 直播回放下载的技术突破与完整指南:解决三大核心难题的实战方案
  • 帝国CMS 7.5编辑器在导入Word文档时如何处理跨平台格式差异?
  • 巧用国内镜像源,一键破解Pyppeteer的Chromium安装难题
  • 腾讯云使用OpenClaw接入个人微信
  • 安卓手机秒变Linux开发机:Termux+Tmoe一键安装KDE桌面全记录
  • 自动驾驶与手动驾驶混合流仿真:基于Matlab的连续型元胞自动机交通流模型源代码解析与可视化研...
  • 实训3 建库、数据处理并导入库
  • 大模型学习干货:一图看懂传统 RAG 与 Agentic RAG 实战差异,小白也能秒理解
  • STM32与51单片机最小系统对比:为什么你的32项目必须加稳压电路?
  • 每日算法题 10
  • Bebas Neue:开源无衬线字体的商业价值挖掘与全场景应用方法论
  • 如何用picacomic-downloader打造个人漫画图书馆?3步轻松搞定离线阅读
  • OP-CEPH02-在OpenEuler 22.03 LTS-SP4上构建高可用CEPH集群实战
  • 技术拆解:AI低代码架构设计与全链路落地实现
  • 科晶生物双擎AI驱动,解锁“蛋白/核酸”大分子定向设计新范式
  • 深度剖析SWAP模型,从SWAP模型源代码编译到AI大语言模型辅助建模
  • COMSOL专业模型在激光熔覆与选区熔融仿真中的应用