• 区间树 学习笔记



    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(nlog 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(nlog 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+Nlog 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)的强制在线还就一主席树题够蠢的)

    ------------------------------------------------------------------------------------------------------------------------
    无心插柳柳成荫才是美丽
    有哪种美好会来自于刻意
    这一生波澜壮阔或是不惊都没问题
    只愿你能够拥抱那种美丽
    ------------------------------------------------------------------------------------------------------------------------
  • 相关阅读:
    呼叫中心获取sip数据报文
    【代码总结】GD库中简单的验证码
    【代码学习】PHP中GD库的使用
    【漏洞详解】文件包含漏洞
    讲两道常考的阶乘算法题
    如何高效解决接雨水问题
    如何判定括号合法性
    二分查找高效判定子序列
    一道数组去重的算法题把东哥整不会了
    如何高效寻找素数
  • 原文地址:https://www.cnblogs.com/SovietPower/p/14399552.html
Copyright © 2020-2023  润新知