KD-tree

固定された多次元点集合に対して、最近傍点探索と直交範囲探索を行います。

点を追加・削除しない静的な点集合に適しています。

型

コンストラクタ

initKDTree[D: static[int], T](
  points: openArray[KDPoint[D, T]],
): KDTree[D, T]

引数

initKDTreeはpointsを内部へコピーします。 元の入力列と各点は変更されません。

返り値

元の入力順は保持され、検索結果のindexはpoints内のindexを表します。

制約

計算量

点数をnとします。

nearest

tree.nearest(
  query: KDPoint[D, T],
): Option[KDNearestResult[T]]

queryに最も近い点を検索します。 距離にはユークリッド距離の2乗を使用します。

引数

返り値

tuple[
  index: int,
  squaredDistance: T,
]

空のKD-treeではnoneを返します。

距離が等しい点が複数ある場合は、 元の入力indexが最小の点を返します。

計算量

点数をnとします。

rangeSearch

tree.rangeSearch(
  lower: KDPoint[D, T],
  upper: KDPoint[D, T],
): seq[int]

軸に平行な半開直方体に含まれる点を検索します。

各次元dについて、次を満たす点が対象です。

lower[d] <= point[d] < upper[d]

引数

各次元についてlower[d] <= upper[d]を満たすものとします。

返り値

範囲内に点がない場合は空列を返します。

計算量

点数をn、出力件数をkとします。

len

tree.len: int

KD-treeに格納されている点数を返します。

使用例

import std/optionsimport atcoder/extra/structure/kd_treelet points: seq[KDPoint[2, int64]] =  @[    [0'i64, 0],    [5'i64, 1],    [2'i64, 2],  ]let tree =  initKDTree(points)let query: KDPoint[2, int64] =  [3'i64, 2]let nearestPoint =  tree.nearest(query).getdoAssert nearestPoint.index == 2doAssert nearestPoint.squaredDistance == 1let lower: KDPoint[2, int64] =  [0'i64, 0]let upper: KDPoint[2, int64] =  [6'i64, 2]doAssert tree.rangeSearch(  lower,  upper,) == @[0, 1]doAssert tree.len == 3

内部実装

各nodeは部分木のbounding boxを保持します。

最近傍探索と範囲探索では、 条件を満たす点を含まない部分木をbounding boxによって枝刈りします。

関連API