博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

区间树 学习笔记


Interval Tree(区间树)

网上好多人把区间树当成线段树。。线段树就叫Segment Tree好吧。几乎只有两篇(现在三篇了)和wiki是真的(也都没有具体的代码)。建议直接看wiki:https://en.wikipedia.org/wiki/Interval_tree (pdf: 链接:https://share.weiyun.com/3WXYiU6b 密码:5c75zn)
https://blog.csdn.net/qiaojialin/article/details/78213061
https://www.cnblogs.com/jcli/p/4574824.html

但是这个东西,没人知道不是没有道理的,是真的,没用

Interval Tree大概分为三种:Centered Interval Tree、Augmented Tree、Medial- or Length-oriented Tree。下面说的为Centered Interval Tree。

实现的功能

给定\(n\)个区间(线段)。对于询问给定的一个区间或点,可以在\(O(\log n+m)\)时间内求出与询问区间相交/包含询问点的所有区间(\(m\)是答案区间的数量)。
构造:\(O(n\log n)\);空间复杂度:\(O(4n)\)

构造

区间树(Centered Interval Tree)是一个二叉树(上面csdn那篇写错了)。
依据所有线段确定一个中间点\(x_{center}\)。设每个区间的端点为\(l,r\)。对于\(r<x_{center}\)的区间分到左子树中构造;\(l>x_{center}\)的区间分到右子树中继续构造;剩下的就是包含\(x_{center}\)的区间,分别按\(l\)从小到大、\(r\)从大到小排序后的两种序列存在当前节点中。
也就是每个节点包含五个信息(原文比较清楚)

  • A center point(\(x_{center}\)
  • A pointer to another node containing all intervals completely to the left of the center point(\(lson\)
  • A pointer to another node containing all intervals completely to the right of the center point(\(rson\)
  • All intervals overlapping the center point sorted by their beginning point(以下记为\(S_a\)
  • All intervals overlapping the center point sorted by their ending point(以下记为\(S_b\)

\(x_{center}\)的选取要保证划分到左右子树中的区间数各不超过\(n/2\),所以可以取所有端点的中位数作\(x_{center}\)(可以用nth_element做到\(O(n)\))。
想一个\(\log\)建树好像是有点麻烦...

查询包含点\(p\)的区间

从根节点开始,若\(p<x_{center}\),则查询当前节点及左子树;若\(p>x_{center}\),查询当前节点及右子树;否则\(p=x_{center}\),当前节点所有区间就是答案。
查询一个节点时,若\(p<x_{center}\)则该节点所有区间的\(r>p\),所以只需枚举\(S_a\)(按左端点排好序)中的区间就可以找到包含\(p\)的所有区间。
所以复杂度\(O(\log n+m)\)

查询与给定区间相交的所有区间

设询问区间为\([q_l,q_r]\)。它与原有区间\([l,r]\)相交有两种可能:\(l\)\(r\)至少有一个点在\([q_l,q_r]\)中;\([l,r]\)完全包含\([q_l,q_r]\)
第一种情况,可以建一棵线段树(csdn那篇用的B+树,没有必要吧),将每个区间插入到\(l,r\)两个位置去,每个节点存\(l\)\(r\)在该节点区间内的所有区间。查询时区间查\([q_l,q_r]\)即可(注意去重,可以合并时归并方便去重,也可以打标记)。复杂度\(O(n\log n),O(\log n+m)\)
第二种情况,建一个Interval Tree。用\([q_l,q_r]\)中任意一点\(p\)求与\(p\)相交的所有区间,然后判断这些区间是否包含\([q_l,q_r]\)。这些区间一定也是答案区间(有可能与情况一重复),所以复杂度仍是\(O(\log n+m)\)

扩展到高维

对于\(N\)维“区间”的查询依旧可以用Interval Tree。
基本同查询与给定区间相交的所有区间。首先建一个\(N\)维Range Tree存所有“区间”,对于每次查询先找出存在某个点 在给定\(N\)维询问区间内 的所有区间,即第一种情况。
对于第二种情况,建\(N\)棵Interval Tree解决每一维,\(N\)维答案的交集就是最终答案。

那个\(N\)维Range Tree,我以为是什么神奇的东西,原来就是。。\(N\)维线段树(线段树套线段树套线段树...)。。所以复杂度是\(O(\log^{N}n+N\log n+Nm)\)的。
那个\(N\)维Range Tree可能可以用K-D Tree写。

应用

挺...局限的。
首先它的作用可以用离线+树状数组/二维线段树实现,可能用到的情况是:强制在线并卡\(\log^2n\)算法。其次它复杂度与答案区间数有关,需要题目保证\(m\)不大,不能任意询问。
例题:2020-2021 ICPC Brazil Subregional Programming Contest. M. Machine Gun(1.2s来卡\(\log^2n\)的强制在线还就一主席树题够蠢的)

posted @ 2021-02-10 23:14  SovietPower  阅读(1061)  评论(3编辑  收藏  举报