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) 第一维,降下来一维
所以后面是个三维偏序,然后上 (K-D Tree)
支持插入一个新点,空间内查询最大值
卡常的话可以先把所有点都建出来