__gnu_pbds::tree 用法简介
__gnu_pbds::tree 用法简介
概述
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
都要带的。
命名空间为 __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>
。
迭代器
使用 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)\)。