核心概述:顺序统计树提供按秩访问与求秩功能的有序集合(非 multiset),典型操作 O(log N),可通过模板参数替换为 map 版本。

原文引述:

Description: A set (not multiset!) with support for finding the n’th element, and finding the index of an element. To get a map, change \texttt{null_type}. Time: O(\log N)

展开阐述:

  • 定义与问题背景、适用场景
    • 面向“有序集合上的秩操作”:支持根据秩找到元素(find_by_order)以及查询某元素的秩(order_of_key)。
    • 适用于在线排名、前 K 小/大、区间第 k 小、顺序统计等常见场景。
    • 注意:这是 set 语义(不允许重复元素);若需要键值对或允许重复需相应改造或包装。
  • 接口与数据结构字段说明(依据实现/示例)
    • 类型别名:
      • Tree = tree<T, null_type, less, rb_tree_tag, tree_order_statistics_node_update>
        • 基于红黑树(rb_tree_tag)并带有顺序统计更新器(tree_order_statistics_node_update)。
    • 关键成员函数:
      • find_by_order(k):返回第 k 个元素的迭代器(0-based),越界则返回 end。
      • order_of_key(x):返回集合中严格小于 x 的元素数量,即 x 的秩。
    • 示例要点(example 提示):
      • 插入与 lower_bound 配合:insert(8), insert(10),检查迭代器与 lower_bound(9) 的关系。
      • 验证秩与按秩访问:order_of_key(10) 1,*find_by_order(0) 8。
      • 合并:t.join(t2) 的演示调用显示可将两棵树合并(需满足内部约束)。
    • Map 版本:
      • “To get a map, change null_type.” 即可将第二模板参数从 null_type 替换为映射的 mapped_type,得到有序 map 的顺序统计版本。
  • 核心操作流程/要点
    • 插入/删除与平衡由底层红黑树维护;顺序统计通过维护子树大小等信息完成。
    • find_by_order 与 order_of_key 通过树上累积信息以 O(log N) 导航至目标。
  • 复杂度与边界条件
    • 所有基本操作(插入、删除、求秩、按秩访问)期望 O(log N)。
    • 非 multiset 语义:插入已存在元素不改变集合大小;如需多重集语义,需要在键中引入“去重器”(如 pair<key, unique_id>)或改其他结构。
    • find_by_order 越界需判空处理;order_of_key 针对严格小于的计数语义要明确。
  • 实现细节与坑
    • 自定义比较器需与等价关系一致,以免顺序统计失真。
    • 合并 join 需要两棵树键域不冲突且满足内部约束;错误使用可能破坏平衡或统计信息。
    • 迭代器在结构修改后可能失效,遵循与标准关联容器类似的有效性规则。
  • 变体/扩展与对比
    • 可替代基于 003-数据结构-树状数组 的“离散化+前缀计数”方案,免除预离散但常数略大。
    • 若只需频次/前缀和且键空间已离散,树状数组/线段树 012-数据结构-线段树 更合适;需要秩与元素互查时该结构更简洁。
  • 正确性要点
    • 红黑树保证对数高度;节点维护的顺序统计信息作为不变式在旋转与插入删除中保持一致,从而保证秩操作正确。

关联节点