BST-Treap名次树指针实现板子 Ver2.1
为了更好的阅读体验,请点击这里
这里只有板子没有原理QWQ
可实现
1.插入 x 数
2.删除 x 数(若有多个相同的数,只删除一个)
3.查询 x 数的排名(排名定义为比当前数小的数的个数 +1)
4.查询排名为 x 的数
5.求 x 的前驱(前驱定义为小于 x,且最大的数)
6.求 x 的后继(后继定义为大于 x,且最小的数)
原题 https://www.luogu.com.cn/problem/P3369
在 Ver1.0 基础上把指针板子修正成 C++ 的类方法版本了,null 指针使用 static 静态量来处理。然后仅需要实现类的方法中包含小于号的重载就可以使用这个名次树了。另外,这里所有涉及到的名次都是 1-index 的。
目前还有迭代器、\(O(n)\) 建树没有实现,剩下的功能都有所实现。查询排名为 \(x\) 的数如果 \(x \not \in [1, sz_{root}]\) 会 RE,前驱和后继如果不存在会返回 null->v。这个实现有点脑浆,所以可能以后还会改。
请务必不要使用 std::swap 直接交换两个 Treap,否则会析构删得什么都不剩!取而代之,可以使用成员函数中的 swap。
#include <bits/stdc++.h>
using namespace std;
template<class T> class Treap {
public:
Treap() {}
~Treap() { _clear(root);}
void insert(T x) { _insert(root, x);}
void erase(T x) { _erase(root, x);}
int rank(T x) { return _GetRankOfVal(root, x);}
T kth(int x) { assert(1 <= x && x <= root->sz); return _GetValOfRank(root, x);}
T pre(T x) { Node *ans = null; query_pre(root, x, ans); return ans->v;}
T nxt(T x) { Node *ans = null; query_nxt(root, x, ans); return ans->v;}
bool empty() { return root->sz == 0;}
int size() { return root -> sz;}
void clear() { _clear(root);}
void swap(Treap<T>& rhs) { std::swap(root, rhs.root);}
private:
struct Node {
Node *ch[2];
T v;
int sz, r, cnt;
Node() { sz = r = cnt = 0;}
Node(const T &v):v(v) { ch[0] = ch[1] = null; r=rand(); sz = cnt = 1;}
bool operator < (const Node& rhs) const { return r < rhs.r;}
int cmp(const T& x) const {
if(!(x < v || v < x)) return -1;
return v < x;
}
void upd() { sz = ch[0] -> sz + ch[1] -> sz + cnt;}
};
static Node *null;
Node *root = null;
void rotate(Node* &o, const int &d) {
Node *k = o->ch[d^1]; o->ch[d^1] = k->ch[d]; k->ch[d] = o;
o->upd(); k->upd(); o = k;
}
void _insert(Node* &o, const T &x) {
if (o == null) { o = new Node(x); return;}
o->sz++;
int d = o->cmp(x);
if (d == -1) {o->cnt++; return;}
_insert(o->ch[d], x);
if (o->r < o->ch[d]->r) rotate(o, d^1);
o -> upd();
}
void _erase(Node* &o, const T &x) {
if (o == null) return;
int d = o->cmp(x);
if (d == -1) {
Node* u = o;
if (o->cnt > 1) {o->cnt--; o->sz--; return;}
if (o->ch[0] != null && o->ch[1] != null) {
int d2 = o->ch[0]->r > o->ch[1]->r;
rotate(o, d2); _erase(o->ch[d2], x);
}
else {
if (o->ch[0] == null) o = o->ch[1]; else o = o->ch[0];
delete u;
}
}
else _erase(o->ch[d], x);
if(o != null) o->upd();
}
int _GetRankOfVal(Node *&o, const T &x) {
if (o == null) return 1;
if (!(o->v < x || x < o->v)) return o->ch[0]->sz + 1;
else if (o->v < x) return o->ch[0]->sz + o->cnt + _GetRankOfVal(o->ch[1], x);
else return _GetRankOfVal(o->ch[0], x);
}
T _GetValOfRank(Node *&o, const int &k) {
if (o == null) return T();
if (!(o->ch[0]->sz < k)) return _GetValOfRank(o->ch[0], k);
else if(o->ch[0]->sz + o->cnt < k)
return _GetValOfRank(o->ch[1], k - o->ch[0]->sz - o->cnt);
return o->v;
}
void query_pre(Node *&o, const T &x, Node *&ans) {
if (o == null) return;
if (o->v < x) { ans = o; query_pre(o->ch[1], x, ans);}
else query_pre(o->ch[0], x, ans);
}
void query_nxt(Node *&o, const T &x, Node *&ans) {
if (o == null) return;
if (x < o->v) { ans = o; query_nxt(o->ch[0], x, ans);}
else query_nxt(o->ch[1], x, ans);
}
void _clear(Node*& o) {
if (o == null || o == NULL) return;
_clear(o -> ch[0]);
_clear(o -> ch[1]);
delete o;
return;
}
};
template<class T> typename Treap<T>::Node* Treap<T>::null = new Node();
struct AAA {
int a;
// AAA(int a = 0):a(a) {}
bool operator < (const AAA& rhs) const {
return a < rhs.a;
}
};
int main() {
#ifdef LOCAL
freopen("test.in", "r", stdin);
#endif
int n; scanf("%d",&n);
int op,y;
Treap<AAA> S;
for(int i=0;i<n;i++) {
scanf("%d%d",&op,&y);
AAA x = AAA{y};
switch(op) {
case 1: S.insert(x); break;
case 2: S.erase(x); break;
case 3: printf("%d\n",S.rank(x)); break;
case 4: printf("%d\n",S.kth(y).a); break;
case 5: printf("%d\n",S.pre(x).a); break;
case 6: printf("%d\n",S.nxt(x).a); break;
}
}
return 0;
}
BST-Treap名次树指针实现板子 Ver2.1的更多相关文章
- 「模板」「讲解」Treap名次树
Treap实现名次树 前言 学平衡树的过程可以说是相当艰难.浏览Blog的过程中看到大量指针版平衡树,不擅长指针操作的我已经接近崩溃.于是,我想着一定要写一篇非指针实现的Treap的Blog. 具体如 ...
- UVa 1479 (Treap 名次树) Graph and Queries
这题写起来真累.. 名次树就是多了一个附加信息记录以该节点为根的树的总结点的个数,由于BST的性质再根据这个附加信息,我们可以很容易找到这棵树中第k大的值是多少. 所以在这道题中用一棵名次树来维护一个 ...
- LA 5031 Graph and Queries —— Treap名次树
离线做法,逆序执行操作,那么原本的删除边的操作变为加入边的操作,用名次树维护每一个连通分量的名次,加边操作即是连通分量合并操作,每次将结点数小的子树向结点数大的子树合并,那么单次合并复杂度O(n1lo ...
- POJ-1442 Black Box,treap名次树!
Black Box 唉,一天几乎就只做了这道题,成就感颇低啊! 题意:有一系列插入查找操作,插入每次 ...
- Treap 实现名次树
在主流STL版本中,set,map,都是BST实现的,具体来说是一种称为红黑树的动态平衡BST: 但是在竞赛中并不常用,因为红黑树过于复杂,他的插入 5 种,删除 6 中,代码量极大(如果你要改板子的 ...
- Treap和名次树
Treap名字的来源:Tree+Heap,正如名字一样,就是一颗简单的BST,一坨堆的合体.BST的不平衡的根本原因在于基于左<=根<=右的模式吃单调序列时候会无脑成长链,而Treap则添 ...
- uvalive 5031 Graph and Queries 名次树+Treap
题意:给你个点m条边的无向图,每个节点都有一个整数权值.你的任务是执行一系列操作.操作分为3种... 思路:本题一点要逆向来做,正向每次如果删边,复杂度太高.逆向到一定顺序的时候添加一条边更容易.详见 ...
- 模板——Treap实现名次树
Treap 是一种通过赋予结点随机权值的一种满足堆性质的二叉搜索树,它很好的解决了二叉搜索树顺序插入组成链式的局限性. 名次树是指在treap的每个结点中添加附加域size,表示以它为根的子树的总结点 ...
- hdu4585 Treap与名次树/STL map(C/C++)
hdu4585 题目地址:https://acm.dingbacode.com/showproblem.php?pid=4585 Shaolin Time Limit: 3000/1000 MS (J ...
- bzoj 3196 Tyvj 1730 二逼平衡树(线段树套名次树)
3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1807 Solved: 772[Submit][Stat ...
随机推荐
- Solution Set - NOI级别真题选做
[NOI2007] 社交网络 Link&Submission. key:Floyd Floyd求出任意两点间最短路,以及最短路的条数.求点 \(k\) 的答案时枚举所有点对 \(i,j\),若 ...
- 四、【转】基于知识图谱的推荐系统(KGRS)综述
以下文章来源于AI自然语言处理与知识图谱 ,作者Elesdspline 导语 本文是2020年针对知识图谱作为辅助信息用于推荐系统的一篇综述.知识图谱对于推荐系统不仅能够进行更精确的个性化推荐,而且对 ...
- 羽夏看Linux内核——简述
写在前面 此系列是本人一个字一个字码出来的,包括示例和实验截图.如有好的建议,欢迎反馈.码字不易,如果本篇文章有帮助你的,如有闲钱,可以打赏支持我的创作.如想转载,请把我的转载信息附在文章后面,并 ...
- Ubuntu空间不足,如何扩容
扩容多少看自己需求 点击确定然后打开虚拟机 使用工具的第一种方法 使用Ubuntu自带的disk,直接搜软件disk,点击进去 选择自己要扩容的磁盘 点击设置,选择resize 你要扩容到多少就拖动到 ...
- JDK源码阅读-------自学笔记(十九)(容器概念初探和泛型概念)
简介 数组存在的优势和劣质 优势 数组是线性序列,从效率和类型检查的角度讲,数组是最好的 劣势 不灵活,数组的大小是预先定义好的,不会随意改变 引入容器 容器这个概念就是装东西的介质,可以理解为能装东 ...
- .NET周刊【5月第2期 2024-05-12】
国内文章 C#在工业数字孪生中的开发路线实践 https://mp.weixin.qq.com/s/b_Pjt2oii0Xa_sZp_9wYWg 这篇文章探讨了C#在工业数字孪生技术中的应用,介绍了三 ...
- 无需重新学习,使用 Kibana 查询/可视化 SLS 数据
1. 场景 现在通过 SLS 的 ES 兼容能力,可以很方便地实现用 Kibana 来查询和可视化 SLS 的数据.对于从 ES 迁移到 SLS 的用户可以继续保留原来的 Kibana 使用习惯.下面 ...
- Flask源码阅读
上下文篇 整个Flask生命周期中都依赖LocalStack()栈?.而LocalStack()分为请求上下文_request_ctx_stack和应用上下文_app_ctx_stack. _requ ...
- go append的坑
b := []int{1,2,3,4,5} slice := b[:2] newSlice := append(slice, 50) fmt.Println(b) fmt.Println(newSli ...
- minio-搭建个人云存储服务
相信风靡全球的亚马逊 AWS S3 的存储云服务大家已经耳熟能详了,如何自己搭建一个私有的S3存储云服务呢?Minio 提供对象存储服务,兼容了 AWS S3 存储协议,用于非结构化的数据存.非结构化 ...