KD - Tree 学习笔记

(这本是 P4169 的一篇无法提交的题解)而 KD - Tree 本身在竞赛中的应用就比较少,又几乎不作为正解出现,所以这里只拿一道例题来举例讲解题意:给定一个二维点集 S ,每次有两种操作:操作 1 : 往点集 S 中加入一个点操作 2 : 给定一个点 (x,y)(x, y)(x,y) ,询问该点到点集 S 中每个点曼哈顿距离的最小值两点 (x1,y1),(x2,y2)(x_1, y_1), (x_2, y_2)(x1​,y1​),(x2​,y2​) 之间的曼哈顿距离定义为:∣x1−x2
摘要由CSDN通过智能技术生成

(这本是 P4169 的一篇无法提交的题解)

而 KD - Tree 本身在竞赛中的应用就比较少,又几乎不作为正解出现,所以这里只拿一道例题来举例讲解

题意:

给定一个二维点集 S ,每次有两种操作:

操作 1 : 往点集 S 中加入一个点

操作 2 : 给定一个点 ( x , y ) (x, y) (x,y) ,询问该点到点集 S 中每个点曼哈顿距离的最小值

两点 ( x 1 , y 1 ) , ( x 2 , y 2 ) (x_1, y_1), (x_2, y_2) (x1,y1),(x2,y2) 之间的曼哈顿距离定义为:

∣ x 1 − x 2 ∣ − ∣ y 1 − y 2 ∣ |x_1 - x_2| - |y_1 - y_2| x1x2y1y2

题解:

这题正解是一个 O ( ( n + m ) log ⁡ 2 2   ( n + m ) ) O((n + m) \log_2^2~ (n + m)) O((n+m)log22 (n+m)) 复杂度的做法,需要用到 CDQ 分治

不过既然是 KD - Tree 的学笔,我们就用 KD - Tree 来做这道题

首先来介绍一下 KD - Tree :


1. 定义 & 前置知识

KD - Tree ,原名 K - Dimension Tree ,是一种可以高效处理 k 维空间信息的数据结构

(然而 OI 中很少考到高维的 DS 题目)

(微信步数显然不是 DS 题目吧)

所以 KD - Tree 在 OI 中的应用大多数是二维(例如这道题),少数会有三维

而且 KD - Tree 据说可以配合其它的一些算法 比如乱搞 来获得较高分数

在学习 KD - Tree 之前,你需要了解如下东西:

  • 平衡树(这里特指替罪羊树)

  • STL 中的 nth_element 函数

没了,就这些,所以 KD - Tree 的入门是比较简单的,学会了上手就会很快

2. 建树过程

类似平衡树,KD - Tree 是一种 BST

但是和 BST 不同,在 k 维空间中,KD - Tree 每个结点参与比较的键值是有 k 个的(即每一维的坐标)

不过 KD - Tree 在检索的时候仍然能保证一定的次序

我们只需要在每一个深度都定义一个参与比较的维度,那么这样在检索时,每次究竟是往左子树走还是往右子树走,只要看这个点在当前检索到的深度的“比较维度”上的键值是多少即可

建树的算法已经给你了,关键是如何选择恰当的方式优化,避免像 BST 一样退化成链

那么有两个问题:

  1. 每个深度怎样选维度?

  2. 每个深度选好维度后怎样选点?

对于第一个问题,我们可以选择 1 ~ k 维轮流来

但是有一种更优的选择方式:选择方差最大的一维,具体证明不明,而且实现据说极为复杂

(识相点就选第一种吧,反正很少有出题人会想到要卡你)

对于第二个问题,显然选这个维度的中位数即可,这样左右两边的结点数是相等的

以上两种方式基本可以保证建树时间复杂度为 O ( n log ⁡ 2 n ) O(n\log_2n) O(nlog2n),深度为 O ( log ⁡ 2 n ) O(\log_2n) O(log2n)

具体实现时,中位数可以使用 STL 中的 nth_element 函数,不会影响复杂度,用法请上网查找

这样讲会很抽象,给一张例图:

首先我们以横坐标为关键字,找到这一维的中位数

排序后即为:

A , H , C , B , E , D , G , F A,H,C,B,E,D,G,F A,H,

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值