「学习笔记」KD Tree

KD-Tree

个人感觉 ( m{KD-Tree}) 在操作的时候是要分割每一维的空间的

就是按照某种方式把空间分割了,常见的有选中位数和方差来敲定是哪一维的

然后在操作的时候在分割后的每个区域内部进行查询,不符合的区域不会进行查询

(暴搜+剪枝的本质展露了)


信息

每个节点要维护的东西

(fa,ls,rs,) 父亲,左右儿子

(pos) 这个点储存的真实点和分割的坐标轴

(mn,mx) 表示几个维度内部当前维的最大最小值

(可以拿来剪枝)

这里:树上的每个节点储存的真实节点的顺序是不一定一样的,分割坐标轴那个变量可能存在相同的

然后同时这里还可以维护子树的一些信息

比如点权极值或者和,子树大小(范围内部点的个数)


建树

对于每个 ([l,r]) 选择区间内部方差最大的维度然后 (split)

这里找方差就是纯粹模拟套公式

(mid) 和线段树一样,然后递归就成的了


查询

本质上就是个暴搜+剪枝

以求解最近最远距离举例

如果要求最近距离,那么枚举 (n) 个点在树上面查询

(算了查询具体去看代码吧,代码极为易懂)

注意如果当前维度的差小于距离,那么意味着另一个儿子也有可能是答案,也得去查询

一般会考虑搞一个估价函数之类的

同时对于答案的记忆化也是常见的操作,比如比当前答案劣就不再查询子树内信息之类的

还有一些基础操作,依题而来

判断k维包含关系,有交集关系,点在空间外的关系

用在矩形框点里面的

(这三个全都是模拟就能得到的)


修改

(先说权值问题)

单点的,直接找到那个点,然后改,(push\_up) 啥的一样做

范围内的,跟线段树一样,找到是不是范围包含,然后标记永久化来一波

如果没交集直接退,有部分交,那么递归

插入

啊这个要用上替罪羊的思想啦,如果有个子树超过平衡因子 (alpha),那么暴力重构它就好了

先回收,再 (build)


这个空间复杂度好像是个 (O(n)) 的,但是时间复杂度就比较玄学,好像还很容易卡 (dots)

例题

Luogu3769 [CH弱省胡策R2]TATT

(sort) 第一维,降下来一维

[f_{i}=maxlimits_{j=1}^{i-1} [f_j+1](b_jge b_i,c_jge c_i,d_jge d_i) ]

所以后面是个三维偏序,然后上 (K-D Tree)

支持插入一个新点,空间内查询最大值

卡常的话可以先把所有点都建出来

原文地址:https://www.cnblogs.com/yspm/p/13435326.html