首页 > 其他分享 >pb_ds 速通

pb_ds 速通

时间:2024-12-16 23:21:03浏览次数:4  
标签:std __ 速通 tree len pb ds

Intro

深度好文

成文过程中参考了大量资料,这里一并谢过。

我在 2024.11.22 调试 LG P2596 到凌晨 00:32:21 破防所以加快学习了 pb_ds

pb_ds: Policy-Based Data Structures。封装了很多有用的数据结构,常用的有:

  • Hash
  • 平衡树
  • 字典树
  • 可持久化平衡树

但是严格上讲 pb_ds 并不属于 STL,只在使用 libstdc++ 为标准库的编译器下可以使用,主要内容位于 namespace __gnu_pbds 中,经 CCF 声明,在 NOI 系列比赛中可以使用(天天用 __lg__gcd 了还怕这个?)

一般而言,pb_ds 常数较大。

使用 pb_ds 需要:

#include <ext/pb_ds/assoc_container.hpp> // 必须引用,理解为底层定义
#include <ext/pb_ds/tree_policy.hpp> // tree
#include <ext/pb_ds/hash_policy.hpp> // hash
#include <ext/pb_ds/trie_policy.hpp> // trie
#include <ext/pb_ds/priority_queue.hpp> // priority_queue

有万能头,但是 Win 无法过编:

#include <bits/extc++.h>

hash & trie

pb_ds 中有两个 Hash:

cc_hash_table<Key, Value>;
gp_hash_table<Key, Value>;

第一个使用了拉链法第二个则是探测法,但是注意到我们有更稳定好用的 std::map 和手动重载后的 std::unordered_map,故在此不做赘述。

trie 类用的也比较少,毕竟手写 Trie 并不困难,而且 Trie 实在是太重要了,包括延伸出的 01-Trie……可以看源文件了解一下成员函数。

__gnu_pbds::trie<string, null_type,
                 trie_string_access_traits<>,
                 pat_trie_tag,
                 trie_prefix_search_node_update> tr;

/* 常用的操作 */
tr.insert(str);
tr.erase(str);
tr.join(another_trie);

// 遍历某一个前缀的所有字符串
std::pair<Trie::iterator, Trie::iterator> range = tr.prefix_range(prefix);
for (auto it = range.first; it != range.second; ++it) {
  cout << *it << endl;
}

priority_queue

Why not try OI-Wiki? and official docs?

学习一下仿函数便于重定义堆的排序,本质上为重载括号运算符,在 Template 中比较常用,使用方法如:

template <typename T>
struct comp {
    bool operator() (const T &x, const T &y) {
        return dis[x] > dis[y];
    }
};

std::priority_queue<int, std::vector<int>, comp> q;

这样我们的 std::priority_queue 就是存储下标,按照 \(dis_i\) 来排序的小根堆。

定义如:

__gnu_pbds::priority_queue<T, Compare, Tag, Allocator>

第四个在 OI 中基本不会用到,Tag 的另外几种可以看 OI-Wiki,但是基本上我们只在自定义非原生元素时使用 pb_ds 的堆,而其中 pairing_heap_tag 的表现是最佳的。

这是一些常用的成员函数:

  • push()(会返回元素位置迭代器)
  • pop()
  • top()
  • size()
  • empty()
  • modify(point_iterator, const key) 重要好用,均摊是 \(\log n\) 的
  • erase(point_iterator)
  • join(__gnu_pbds::priority_queue &x) 重要好用,合并到当前堆的同时清空 \(x\)

tree

Why not try OI-Wiki? and official docs?

定义如:

__gnu_pbds::tree<Key, Mapped, Cmp_Fn = std::less<Key>, Tag = rb_tree_tag,
                 Node_Update = null_tree_node_update,
                 Allocator = std::allocator<char>>

其中注意到:

  • Mapped 表示映射规则,一般而言我们使用 null_type 表示无映射(类似于丢进 std::set 里);若关联到带值的集合(类似于丢到 std::map 里),则填入类似 std::map<Key, Value> 中的 Value 类型。
  • Tag 表示底层平衡树类型,一般而言我们使用 rb_tree_tag,这是一种跑得飞快但是极为难调难写的平衡树
  • Node_Update 一般使用 tree_order_statistics_node_update,因为我们需要使用 order_of_keyfind_by_order

这是一些常用的成员函数(基于 Cmp_Fn 比较):

  • insert(x) 返回 std::pair<point_iterator, bool>
  • erase(x) 删除一个元素或迭代器
    • \(x\) 为迭代器:返回下一个迭代器,若为末尾则返回 end()
    • \(x\) 为元素:返回是否删除成功(不存在就删除失败咯)
  • order_of_key(x):返回从 \(0\) 开始的排名
  • find_by_order(x) 返回对于排名所对于元素的迭代器
  • lower_bound(x) 前驱
  • upper_bound(x) 后继
  • join(x)比较函数和元素类型 相同的情况下合并两棵 tree 到当前树,清空 \(x\)
  • split(x, b) 小于等于 \(x\) 的属于当前树,其余的属于 \(b\) 树
  • empty()
  • size()

!!!join(x) 函数需要保证两棵树的值域 不相交(也就是并入树内所有值必须全部 \(\gt / \lt\) 当前树内的所有值),否则会 throwjoin_error

如果要合并两棵树且有交集,则需要将一棵树的元素一一插入到另一棵树中

rope

用于实现可持久化数组、可持久化平衡树。

如前文所述,严格来说,pb_ds 不属于 STL,然而 rope 不属于 pb_ds,头文件位于 rope,在命名空间 __gnu_cxx 中。

__gnu_cxx::rope 支持:

  • at(x) / operator[]:\(O(1)\)
  • push_back() / append:\(O(\log n)\)
  • insert(x, other)x 的位置插入另一个串:\(T_{\min} O(\log n) / T_{\max} O(n)\)
  • erase(x, len) 删除 x 位置开始的 len 个元素:\(O(\log n)\)
  • replace(x, len, other)x 位置开始的 len 个位置替换为 otherlen 可省略:\(O(\log n)\)
  • substr(x, len)x 开始 len 位截取:\(O(\log n)\)
  • operator + 联结两个 rope

黑科技:支持 \(O(1)\) 复制,还不炸空间:

constexpr int N = 1e5 + 7;

rope<int> *his[N];
his[i] = new rope<int> (*his[i - 1]);

标签:std,__,速通,tree,len,pb,ds
From: https://www.cnblogs.com/xsyc/p/18611299

相关文章

  • [USACO06NOV] Corn Fields G
    题目Description农场主 John 新买了一块长方形的新牧场,这块牧场被划分成 M 行 N列 (1≤M≤12,1≤N≤12),每一格都是一块正方形的土地。 John 打算在牧场上的某几格里种上美味的草,供他的奶牛们享用。遗憾的是,有些土地相当贫瘠,不能用来种草。并且,奶牛们喜欢独占一块草地......
  • [BootstrapBlazor] Blazor 使用 Mermaid 渲染详细图表
    BootstrapBlazor是一套基于Bootstrap和Blazor的企业级组件库,无缝整合了Bootstrap框架与Blazor技术。它提供了一整套强大的工具,使开发者能够轻松创建响应式和交互式的Web应用程序。项目地址Gitee:https://gitee.com/LongbowEnterprise/BootstrapBlazorGitHub:https://g......
  • Dot Foods EDI 需求分析及对接流程
    DotFoods是一家美国领先的食品和非食品产品的中间批发分销商,主要为食品服务、零售和分销行业的客户提供服务,是北美大型食品中间分销商之一。DotFoods(以下简称Dot)的业务模式是通过整合多个供应商的产品,为客户提供小批量、多样化的货品,从而帮助客户降低库存成本并提高运营效率......
  • Yolo11改进策略:卷积篇|DSConv,高效卷积算子|附代码|即插即用
    摘要论文介绍研究背景:神经网络量化是提升速度和降低内存使用量的常用方法,但无标记数据的量化问题受到的关注较少。研究目的:引入DSConv卷积算子,旨在生成更小且推理速度更快的神经网络,同时保持高精度。实验验证:在最流行的神经网络架构(ResNet、DenseNet、GoogLeNet、AlexNet......
  • loadSend:免费开源局域网数据传输工具 全平台支持 传输工具
    前言不同系统的电脑、手机,文件传输有没有简单一点的方法?手机是iPhone,电脑是Windows,如何更快捷传输文件呢?我们最常用和用得最多的文件传输工具可能就是微信以及QQ了吧!其实,如果只是在局域网内,用微信这一类聊天工具来传输文件并不算特别合适,除了可能存在的文件大小限制,最大的问......
  • 700PB数据的数仓依然“快稳省”!ByteHouse这本白皮书揭秘关键(内附下载链接)
    12月10日,《火山引擎ByteHouse云数仓产品白皮书》在线上发布。 在数字经济蓬勃发展的今天,企业面临着数据量爆炸性增长、数据分析需求日益复杂的双重挑战。传统的数据仓库解决方案已经难以满足企业对数据处理速度和灵活性的高要求。为了应对这些挑战,火山引擎于2021年正式推出Byt......
  • Halcon中watersheds(Operator)算子原理及应用详解
    在Halcon中,watersheds算子是一种基于灰度值的拓扑关系进行图像分割的方法。该算子的原型为watersheds(Image:Basins,Watersheds::),其中Image为输入的图像,Basins为分割后得到的盆地区域,Watersheds为分割的边界线。以下是对watersheds(SmoothedByte,Basins,Watershed......
  • LT1121IST-5#TRPBF 规格书 数据手册具有关断功能的微功率低压差稳压器芯片
    LT1121/LT1121-3.3/LT1121-5是具有关断功能的微功率低压差稳压器。这些设备能够以0.4V的压降提供150mA的输出电流。这些设备设计用于电池供电系统,低静态电流(30µA运行,16µA关断)使其成为理想的选择。静态电流得到良好控制,不会像许多其他低压差PNP稳压器那样在压降时上升。LT1121/L......
  • 在PbootCMS中遇到“帐号格式不正确,请输入正确的邮箱帐号!”的错误如何解决?
    在PbootCMS中,会员注册过程中有时会遇到“帐号格式不正确,请输入正确的邮箱帐号!”的错误提示。这个问题通常是由于邮箱地址中包含了一些特殊符号,而PbootCMS默认的正则校验规则没有考虑到这些情况。以下是一些解决方法:更换邮箱地址:最简单的方法是更换一个不包含特殊符号的邮箱地......
  • PbootCMS如何自定义栏目和文章的URL路径?
    PbootCMS提供了强大的自定义URL路径功能,使得网站的URL结构更加灵活和友好。以下是详细的步骤和应用场景,帮助你自定义栏目和文章的URL路径:自定义栏目URL路径在PbootCMS中,可以通过在栏目的URL名称中进行定义来实现自定义URL路径。具体操作如下:进入PbootCMS后台管理系统。导......