首页 > 其他分享 >K-D Tree

K-D Tree

时间:2024-11-17 14:46:18浏览次数:1  
标签:子树 int tr Tree mid KDT 节点

0.前言

K-D Tree 是一种能够处理高维空间信息的数据结构,其在一些情况下能够代替 CDQ 分治以及树套树,较优秀地处理 \(k\) 维空间上的信息。

参考资料:OI-wiki

题单:\(\tt{Link}\)

1.KDT 的原理

KDT 的结构与 BST 类似,其每一个非叶子节点都具有超平面的作用,建树时会选择 \(k\) 维中某一维的值作为基准,将空间分割为两个半空间。KDT 上一个节点及其子树所形成的是一个 \(k\) 维长方体,子树中的每个点都在这个长方体内。非叶子节点的左儿子子树中的点均在超平面的左边,右儿子子树中的点均在超平面的右边。

2.KDT 建树

KDT 的建树过程可以看做不断地选择轴用以垂直分割面,然后分别递归到左子树与右子树进行再次选择、递归,而由于应当选择哪一维我们并不确定,选择哪个节点作为父节点也不确定,KDT 的形态结构与时间复杂度正确性就难以保证。
最优情况下,我们会这样建树而使得建出来的 KDT 更加平衡,树高更接近于 \(\log n\):首先轮流选择每一维作为轴垂直分割面,然后取这一维上的中位数为分割点,分割出左右子树。这样建树的时间复杂度为 \(\mathcal{O(n \log n)}\),而对于选择出中位数方式,可以采用 nth_element 函数。

il void build(int &u,int l,int r,int d = 0) {
    int mid = l + r >> 1;
    nth_element(b + l,b + mid,b + r + 1,[d](int x,int y) { return tr[x].x[d] < tr[y].x[d]; });
    u = b[mid];
    if (l < mid) build(tr[u].l,l,mid - 1,(d + 1) % 3);
    if (mid < r) build(tr[u].r,mid + 1,r,(d + 1) % 3);
    pushup(u);
    return ;
}

3.在 KDT 上插入节点:二进制分组重构

我们对插入进来的节点维护最多 \(\log n\) 棵 KDT,每棵的大小均为 \(2^{c}(c \in \mathbb{N})\),每当有相同大小的 KDT,就直接将其拍扁为序列重构,合并为大小为 \(2^{c + 1}\) 的 KDT。这样进行二进制分组,插入节点的均摊时间复杂度就为 \(\mathcal{O(n \log^2 n)}\)。而在询问的时候,将 \(\log n\) 棵树的信息依次询问出来合并即可。

拍扁:

il void append(int &p) {
    if (!p) return ;
    b[++ tot] = p;
    append(tr[p].l); append(tr[p].r);
    return p = 0,void();
}

重构:

tr[++ idx] = {{x,y},w};
b[tot = 1] = idx;
for (int siz = 0; ; ++ siz )
    if (!rt[siz]) { build(rt[siz],1,tot); break; }
    else append(rt[siz]);

4.KDT 上查询信息

通常题目会要求询问一个 \(k\) 维长方体内的某种信息,我们可以类似线段树一样的对 KDT 维护一些东西:当前节点子树所维护的 \(k\) 维长方体在 \(k\) 维上坐标的区间,以及询问的答案信息。可以像线段树一样写一个 pushup 函数,合并左右儿子节点的信息到当前节点上。

这样维护之后,每次查询就能判断当前节点及其子树所维护的区间:

  1. 被包含在查询区间中;
  2. 与查询区间没有交集;
  3. 与查询区间有交集但不被包含。

从而递归合并信息。这样的时间复杂度为 \(\mathcal{O(n^{1 - \frac{1}{k}})}\),不会证明,如果对证明有兴趣的读者可转至 OI-wiki

il int query(int u) {
    if (!u) return 0;
    bool fl = 0;
    rep(k,0,1) fl |= (!(L.x[k] <= tr[u].mn[k] && tr[u].mx[k] <= R.x[k]));
    if (!fl) return tr[u].s;
    rep(k,0,1) if (R.x[k] < tr[u].mn[k] || tr[u].mx[k] < L.x[k]) return 0;
    fl = 0; int ret = 0;
    rep(k,0,1) fl |= (!(L.x[k] <= tr[u].x[k] && tr[u].x[k] <= R.x[k]));
    if (!fl) ret = tr[u].val;
    return ret += query(tr[u].l) + query(tr[u].r);
}

5.KDT 的最近邻搜索

最近邻搜索即在空间中寻找最近点对。同样也可以做到最远,以及扩展到第 \(k\) 近/远。

其过程如下:

  1. 因为 KDT 中每个节点都是空间中的一个点,我们先合并当前点的信息;
  2. 采用启发式搜索的方式,计算出询问的点到当前点的左子树维护的长方体和右子树维护的长方体的最近/远距离;
  3. 判断是否比当前最优点更加优秀,分别递归到左右子树中去查找,这里还有一个优化方式:对于左右子树,优先去更优秀的子树中查找,查找完毕后,判断另一个子树的值(即 2. 中提到的最近/远距离)是否比当前最优点更优,决定是否进入子树查找。

注意:这样的时间复杂度其实并不正确,最坏时间复杂度是 \(\mathcal{O(nq)}\) 的,\(q\) 是询问次数。

6.KDT 练习题单

\(\tt{Link}\)

这里收录了一些 KDT 的典题、好题。

标签:子树,int,tr,Tree,mid,KDT,节点
From: https://www.cnblogs.com/songszh/p/18550544/KDTree

相关文章

  • DSU on Tree
    OIWIKI何为DSUonTree其实是一个CF算法标签即为树上启发式合并,既然为启发式合并,必然会有一些人类智慧的存在(相当于卡常)。DSUonTreeStep1.找出重儿子这里就是重链剖分中的定义就行了。Step2.暴力对于所有的儿子,我们直接先按照题意暴力一遍。对于所有的轻儿子,我......
  • 6-tree
    树基本概念树的基本概念树:nnn个结点的有限集(树是一种递归的数据结构,适合于表示具有层次的数据结构)。是递归定义的。根结点:只有子结点没有父结点的结点。除......
  • 【学习笔记】Segment Tree Beats/吉司机线段树
    链接区间最值操作HDU-5306支持对区间取\(\min\),维护区间\(\max\),查询区间和。很容易想到一个暴力,我们每一次找出这个区间的最大值\(mx\),如果\(mx>x\),那么暴力修改这个位置的值,否则已经修改完毕,退出,时间复杂度为\(O(n^2\logn)\)。打一打补丁,对线段树上的每一个区间维......
  • LSM-TREE一种高效的索引数据结构
    LSM-tree主要目标是快速地建立索引。B-tree是建立索引的通用技术,但是,在大并发插入数据的情况下,B-tree需要大量的磁盘随机IO,很显然,大量的磁盘随机IO会严重影响索引建立的速度。特别地,对于那些索引数据大的情况(例如,两个列的联合索引),插入速度是对性能影响的重要指标,而读取相对来说......
  • elementPlus中的el-tree
    将接口返回的数据整理成组件支持的数据结构接口返回的数据格式:[{"id":767947,"appName":"生生世世","appBundle":"cds","appStore":2,"link":"www.baidu.com","accountId":"3,68","......
  • 界面控件DevExpress WPF中文教程:TreeList视图及创建分配视图
    DevExpressWPF拥有120+个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpressWPF能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。无论是Office办公软件的衍伸产品,还是以数据为中心......
  • cmu15545-数据访问方式:B+树(B+Tree)
    目录基本概念基于磁盘的B+树查询与索引设计选择结点大小(NodeSize)合并阈值(MergeThredshold)变长键(Variable-lengthKeys)结点内部搜索(Intra-NodeSearch)优化手段PointerSwizzlingBε-treesBulkInsertPrefixCompressionDeduplicationSuffixTruncation基本概念基于磁盘的B+树......
  • 力扣 653. 两数之和 IV 二叉树/binary-tree two-sum IV
    数组系列力扣数据结构之数组-00-概览力扣.53最大子数组和maximum-subarray力扣.128最长连续序列longest-consecutive-sequence力扣.1两数之和N种解法two-sum力扣.167两数之和IItwo-sum-ii力扣.170两数之和IIItwo-sum-iii力扣.653两数之和IVtwo-sum-IV力......
  • KDTree求平面最近点对
    更新日志思路对于每一个点都求一边其最短距离,最后统计。详细地,对于每个区间,先与其中点判断并更新距离(注意特判不能是同一点),然后找出在这一节点排序维度上,查询点到中点距离,记作\(D\)。看查询点在中点左侧/右侧,判断去左右区间。(在这一节点排序的维度上。)同侧更新完之后,如果......
  • Matrix-Tree 定理 & BEST 定理
    矩阵树定理感谢这篇文章对我更深层次理解矩阵树定理的帮助。预备知识行列式图的关联矩阵对于一张无向图\(G=(V,E)\),定义其关联矩阵\(M\)为(在此我们给边暂定方向,一条边\(e\)的入点和出点分别为\(\text{in}(e)\)和\(\text{out}(e)\)):\[M_{i,j}=\begin{cases}1&V_i=\t......