李超线段树
引入¶
洛谷 4097 [HEOI2013]Segment
要求在平面直角坐标系下维护两个操作(强制在线):
- 在平面上加入一条线段。记第 i 条被插入的线段的标号为 i,该线段的两个端点分别为 (x_0,y_0),(x_1,y_1)。
- 给定一个数 k,询问与直线 x = k 相交的线段中,交点纵坐标最大的线段的编号(若有多条线段与查询直线的交点纵坐标都是最大的,则输出编号最小的线段)。特别地,若不存在线段与给定直线相交,输出 0。
数据满足:操作总数 1 \leq n \leq 10^5,1 \leq k, x_0, x_1 \leq 39989,1 \leq y_0, y_1 \leq 10^9。
我们发现,传统的线段树无法很好地维护这样的信息。这种情况下,李超线段树 便应运而生。
概述¶
我们设法维护每个区间中,可能成为最优解的线段。
称一条线段在 x=x_0 处最优,当且仅当该线段在 x_0 处取值最大。
称一条线段能成为区间 [l,r] 中的 最优线段,当且仅当:
- 该线段的定义域完整覆盖了区间 [l,r];
- 该线段在区间中点处最优。
现在我们需要插入一条线段 f,在这条线段完整覆盖的区间中,某些区间的最优线段可能发生改变。
考虑某个被新线段 f 完整覆盖的区间,若该区间无最优线段,则该线段可以直接成为最优线段。
否则,设该区间的中点为 m,我们拿新线段 f 在中点处的值与原最优线段 g 在中点处的值作比较。
首先,如果新线段 f 斜率大于原线段 g,
- 如果 f 在 m 处更优,则 f 在右半区间 一定 最优,g 在左半区间 可能 最优;
- 反之,g 在左半区间 一定 最优,f 在右半区间 可能 最优。
接下来考虑 f 斜率小于 g 的情况,
- 如果 f 在 m 处更优,则 f 在左半区间 一定 最优,g 在右半区间 可能 最优;
- 反之,g 在右半区间 一定 最优,f 在左半区间 可能 最优。
最后考虑新线段和旧线段斜率相同的情况,此时只需比较截距即可,截距大的一定在整个区间内更优。
确定完当前区间的最优线段后,我们需要递归进入子区间,更新最优线段可能改变的区间。
这样的过程与一般线段树的递归过程类似,因此我们可以使用线段树来维护。
现在考虑如何查询一个区间的最优线段。
查询过程利用了标记永久化的思想,简单地说,我们将所有包含 x_0 区间(易知这样的区间只有 O(\log n) 个)的最优线段拿出来,在这些线段中比较,从而得出最优线段。
根据上面的描述,查询过程的时间复杂度显然为 O(\log n),而插入过程中,我们需要将原线段分割到 O(\log n) 个区间中,对于每个区间,我们又需要花费 O(\log n) 的时间更新该区间以及其子区间的最优线段,从而插入过程的时间复杂度为 O(\log^2 n)。
[HEOI2013]Segment 参考代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | |
build本页面最近更新:,更新历史
edit发现错误?想一起完善? 在 GitHub 上编辑此页!
people本页面贡献者:OI-wiki
copyright本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用