K-D Tree
\(k-D Tree\) 是一种可以 高效处理 \(k\) 维空间信息 的数据结构。
在结点数远大于 \(k\) 时,应用 \(k-D Tree\) 的时间效率很好。
—— OI Wiki
对于建树,主流写法是平衡树版,时空复杂度较小,由于本人码力过于匮乏,所有实现均采用线段树版
每次折半理论上应该计算方差,然而一般横纵坐标交替处理的表现已经足够优秀
由于在多数情况下 \(k-D tree\) 的理论复杂度并不正确,所以应该尽量多的使用各种剪枝,尤其是左右儿子递归顺序的判断上
应用之一是寻找点与点的关系
进入每个子树时判断这个子树表示的举行与当前点的最大/小距离是否足以更新答案,如果不行直接返回
又是一个神奇的套路
要求 \(k\) 远点,那么开个堆存储当前最大的 \(k\) 个元素,每次替换对顶
在 \(KDT\) 上像线段树一样 \(update\),保存子节点的和
用一样的方式在进入时用边界点进行剪枝
首先明确 \(KDT\) 只能维护点,那么把所有点插入
将所有矩形从低到高枚举,匹配子树内满足条件的编号最小的点
注意匹配后需要将点删除,即把权值设为正无穷
一定要注意的一点是由于建树过程中一直在 \(nth\_element\),所以原数组的下标一直在变,应当以编号为基准
如果涉及强制在线的动态插入,很可能让整棵树变得极不平衡
既然不能旋转,只好采用类似于替罪羊树的方式进行重构
发现加了个第 \(k\) 大的操作,那么转化为线段树(二分)套 \(KDT\)
在线段树每个节点的 \(KDT\) 中插入新点,并且分别重构
查询时进入左右儿子时二分判断
由于线段树版本常数过大,至今没有在洛谷上卡过去……
首先将所有询问离线,将矩形动态插入,同时更新每个点最右的操作,转化为 \(last\ge l\) 的权值和
开另一个数据结构去维护这个覆盖操作,应当转化为维护最右操作为 \(i\) 的点的权值和
覆盖时在线段树上用当前标记更新以前标记时把以前标记产生的贡献消除
复杂度均摊下来是正确的
由于 \(KDT\) 自带根号,可以采用值域分块维护