KD-tree

Supports nearest-neighbor and orthogonal-range queries on a fixed multidimensional point set.

General form

let tree =
  initKDTree(points)

let nearestPoint =
  tree.nearest(query)

let indices =
  tree.rangeSearch(
    lower,
    upper,
  )

Parameters and types

initKDTree copies the input point sequence. It does not modify the input.

Preconditions

Return values and side effects

nearest(query) returns:

Option[
  tuple[
    index: int,
    squaredDistance: T,
  ]
]

It returns none for an empty tree. Distance ties are resolved by the smallest original input index.

rangeSearch(lower, upper) returns sorted original input indices satisfying:

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

in every dimension. The query box is half-open.

tree.len returns the number of points.

Example

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 nearestPoint =  tree.nearest(    [3'i64, 2]  ).getdoAssert nearestPoint.index == 2doAssert nearestPoint.squaredDistance == 1doAssert tree.rangeSearch(  [0'i64, 0],  [6'i64, 2],) == @[0, 1]

A KD-tree is useful for nearest-neighbor search and coordinate-range reporting.

Complexity and implementation

Let n be the number of points, D the dimension, and k the output size.

Each node stores its subtree bounding box. Queries prune subtrees whose boxes cannot improve or intersect the answer.