【杂谈】k-d tree 矩形区域查询复杂度

概述

就是一直很不理解的, k-d tree \text{k-d tree} k-d tree 的区间查询的复杂度。

算法流程

  • 查询一个矩形区域,如果与当前区域无交集,立刻 r e t u r n \tt return return
  • 如果当前区域被完全包含,立刻 r e t u r n \tt return return
  • 否则往左右子树分别递归。记此类点的数量为 γ \gamma γ

时间复杂度

r e t u r n \tt return return 了的节点,都存在一个没有 r e t u r n \tt return return 的父节点,所以数量不超过 2 γ 2\gamma 2γ 。设 访问一个节点的复杂度是 O ( 1 ) \mathcal O(1) O(1),则查询复杂度是 O ( γ ) \mathcal O(\gamma) O(γ) 。问题在于求出 γ \gamma γ

k-d tree \text{k-d tree} k-d tree 是仿照线段树而诞生的(我猜的),所以也要仿照线段树的复杂度证明。即,如果往左右子树分别递归,那么一定是 划分线(当前点对应的那条分割线)跨过了查询区间。这会导致子节点的查询区间都 紧贴边缘(查询区间紧贴划分线,划分线就是子节点的边缘)。

对于某一维,用 0 , 1 , 2 0,1,2 0,1,2 表示查询区间紧贴着多少个边缘。那么划分线把它 “切开” 就会导致 0 → 1 , 1 0\to 1,1 01,1 1 → 1 , 2 1\to 1,2 11,2 2 → 2 , 2 2\to 2,2 22,2 。而每一维都是 2 2 2,就是被完全包含,此时会 r e t u r n \tt return return,不能统计。

最初,每一维都是 0 0 0 。若不 “切开”,则下一层点数不变,而 “切开” 可以使得点数翻倍。贪心地想,最坏情况肯定是直接把 0 0 0 都 “切开” 成 1 , 1 1,1 1,1 。于是,过了 k k k 层,我们就获得了 2 k 2^k 2k 个每一维都是 1 1 1 的状态。

接下来就只有 1 → 1 , 2 1\to 1,2 11,2 2 → 2 , 2 2\to 2,2 22,2 两种转移。它可以看成有向图的行走(矩阵乘法)。那么,假如有 x x x 移动,即 x k xk xk 层,那么枚举 1 1 1 第一次走到 2 2 2 的时间 t t t,则该维上的行走情况数是 ∑ t = 0 x 2 x − t = 2 x + 1 − 1 \sum_{t=0}^x2^{x-t}=2^{x+1}-1 t=0x2xt=2x+11 。每一维都走到 2 2 2 是不合法的(不在 γ \gamma γ 统计范畴内),于是枚举一个维度没走到 2 2 2,剩下的维度都乱走,则总情况数有上界 k ⋅ ( 2 x + 1 − 1 ) k − 1 k\cdot (2^{x+1}{\rm-}1)^{k-1} k(2x+11)k1 。为何是上界?因为有很多种情况算重了。

层数共 log ⁡ n \log n logn,再减去最初用于 “切开” 的 k k k 层,轮数 x = log ⁡ n − k k x=\frac{\log n-k}{k} x=klognk 。代入上式得
k ( n k − 1 ) k − 1 k\left(\sqrt[k]{n}-1\right)^{k-1} k(kn 1)k1

其实这只是最底层的 γ \gamma γ 点数量。但是 ( 2 x + 1 ) k − 1 (2^{x+1})^{k-1} (2x+1)k1 是指数级增长,较小的 x x x 一定得到高阶无穷小,所以在下面的 big- O \text{big-}\mathcal O big-O 中可以忽略。——线段树则是 k = 1 k=1 k=1 的特例,此时它不是指数级增长,必须求和,所以是 O ( log ⁡ n ) \mathcal O(\log n) O(logn)

最后乘上起点的系数 2 k 2^k 2k,用 O \mathcal O O 做简化得
O ( 2 k k n 1 − 1 k ) \mathcal O(2^kkn^{1-{1\over k}}) O(2kkn1k1)

我感觉复杂度就是这个。而有人似乎能证明是 O ( k n 1 − 1 k ) \mathcal O(kn^{1-{1\over k}}) O(kn1k1) 的,对此我只能表示: O ( k n 1 − 1 k ) ⫅ O ( 2 k k n 1 − 1 k ) \mathcal O(kn^{1-{1\over k}})\subseteqq\mathcal O(2^kkn^{1-{1\over k}}) O(kn1k1)O(2kkn1k1),所以我也没错(手动滑稽)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值