省选算法复习
1. 线段树优化建图
当我们需要向区间内所有点连边或者从区间中所有点连到某个点的时候,便可以使用线段树来优化,如果需要从区间每一个点连到另一个区间每一个点的话,加一个虚点就好了。
这不是一个很困难的技巧,关键在于要建模。
P5471 [NOI2019] 弹跳 - 洛谷
本题,要求从一个点连接到一个矩形里面的所有点。然后求最短路径。
14-18 号测试点就是模板线段树优化建图。9-13 号测试点是直接建图。1-8 是暴力。
那么 KDT 其实也可以优化建图,但是空间太小了,运气好也许能过 19-22.
只是简单地进行一维技巧的二维扩展好像是比较无效的,因为这种情况下你很难指定第二位应该连哪些边。
现在的问题是要建立的边有 \(\mathcal O(m\sqrt n)\) 条,存不下。
2. KDT
KDT 是维护高维点集的有力结构。其结构保证:点数 \(\mathcal O(n)\) 树高 \(\mathcal O(\log n)\) 矩形查询 \(\mathcal O(\sqrt n),\text{general form }\mathcal O(n^{1-1/k})\)
我们可以继续看这个题,qwq
考虑无论边有多少条,能到达的点最多 n 个,而建图的目的就是快速遍历所有能够到达的点。所以不把边建出来即可。
另外,本题也可以不使用 KDT 优化建图,见杂题日推 I,这种方法更巧妙。
查询复杂度分析
容易知道,一次查询的复杂度就是部分被查询区间包含的节点个数,我们先考虑完全包含查询区间的节点,这至多有 \(\mathcal O(\mathbf{height})=\mathcal O(\log n)\) 个,而不完全包含的,如上图。
对于当前节点,若子树大小为 \(n\),那么考虑画出它儿子、孙子的划分,上图中每一份的子树大小都是 \(n/4\),我们可以对查询矩形的每一条边来考虑,发现矩形的一条边至多穿过两个孙子,然后对于每一个被穿过的孙子,递归考虑,可以写出:
由主定理,\(T(n)=\mathcal O(\sqrt n)\)。
插入删除
我们有两种策略
-
插入/删除的个数超过一定阈值就全局重构,单次修改均摊 \(\mathcal O(n\log n/B)\),查询均摊 \(\mathcal O(B+n^{1-1/k})\)。
-
适用于仅有插入的情况,这同样对其他大量不支持插入的数据结构管用,即二进制分组,插入时,新建大小为 1 的某数据结构,然后不断将大小相同的拿来拍平重构。这样,如果最后数据结构有 \(n\) 个点,那么总插入复杂度就是 \(\mathcal O(n\log^2 n)\)。
注意用替罪羊维护是假的。