__gnu_pbds::tree 用法简介
__gnu_pbds::tree 用法简介
太长不看版
每次操作的复杂度是 \(O(\log n)\)。
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
// or #include<bits/extc++.h>
__gnu_pbds::tree<Key,null_type,less<Key>,rb_tree_tag,tree_order_statistics_node_update> tr1,tr2;
// Key 为数据类型,less<Key> 为比较方式,注意元素都是不可重的,需要可重可以 pair<Key,时间戳>
tr1.order_of_key(x); // 返回值为 x 的排名,从 0 开始编号
tr1.find_by_order(k); // 返回第 k 小,从 0 开始编号
tr1.split(k,tr2); // 将值大于 k 的元素分裂出去到树 tr2
tr1.join(tr2); // 值域不交的合并
// 其他操作同 std::set
概述
pbds即平板电视,里面实现了很多数据结构,NOI系列赛事可以使用,但很多 OJ 和网站无法使用。
其中有 __gnu_pbds::tree,是平衡树,支持查找位置、查找第 \(k\) 大、分裂、合并。功能远强与 std::set。
性能
实现是红黑树,空间常数是 Treap 的 \(1.5\) 倍,时间常数是 Treap 的 \(1.1\) 至 \(1.2\) 倍。
效率还可以,空间回收优秀,大部分平衡树题都可以用。
用法
库文件 & 命名空间
头文件
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
其中第一个头文件是使用 pbds 都要带的。
当然你可以使用
#include<bits/extc++.h>
但是如果使用 winlibs-gcc 会少一个文件。
命名空间为 __gnu_pbds。
注意你不应 using namespace __gnu_pbds,因为它和 std 都有 priority_queue,并且它还包含 tree trie 这样名字的数据结构。
定义
__gnu_pbds ::tree<Key, Mapped, Cmp_Fn = std::less<Key>, Tag = rb_tree_tag,
Node_Update = null_tree_node_update,
Allocator = std::allocator<char> >
Key存储的数据类型,注意不能存储多个值相同的元素,若需要可以用 pair 或封成 struct多存一个时间戳。
Mapped 映射类型,如果无映射类似于 std::set,此处需填 __gnu_pbds::null_type,若有映射,如 std::map,应填映射类型,类似于 std::map<Key,Value> 的 Value 类型。
Cmp_Fn 比较类型,默认从小到大,其用 std::less<Key>,从大到小可用 std::greater<Key>,若是自定义类型,这两者都需要重载小于号。
Tag 底层数据结构,默认为 rb_tree_tag,红黑树,速度最快。还可选 splay_tree_tag 和 ov_tree_tag 速度较慢别用。
Node_Update 更新节点的策略,可用于进阶操作,这里不提及。
Allocator 空间分配器类型,你不用管它。
-
一般来说,你只需要用无映射基础版本即可,即
tree<Key,null_type>。 -
注意如果需要使用查第 \(k\) 小和查排名,那么需要使用
tree<Key,null_type,less<Key>,rb_tree_tag,tree_order_statistics_node_update>。
迭代器
使用 iterator访问迭代器:
tree::iterator
同时它有 .begin() 和 .end(),用法和 std::set 类似。
成员函数
-
size()empty(),用法类似。 -
insert(x)用法类似,插入元素,返回一个pair:first是迭代器,second是一个bool表示是否插入成功 -
erase(x),用法类似,删除值为x的元素或删除迭代器为x的元素,删除迭代器后迭代器失效。函数返回一个bool表示是否成功。 -
lower_bound(x)upper_bound(x),用法类似,第一个大于等于和第一个大于,返回迭代器。 -
order_of_key(x)返回值为 \(x\) 的排名,按定义的比较方式比较。 -
find_by_order(x)返回按比较方式比较的第 \(x\) 小的迭代器。 -
x.join(y)将 \(y\) 树并入 \(x\) 树,\(y\) 被删除。前提是两棵树值域互不相交。 -
x.split(k,y)分裂,值小于等于 \(k\) 的属于 \(x\) 树,剩下的属于 \(y\) 树。
以上函数的时间复杂度均为 \(O(\log n)\)。

浙公网安备 33010602011771号