1. 程式人生 > 其它 >[筆記] K-D Tree

[筆記] K-D Tree

一種可以 高效處理 \(k\) 維空間資訊 的資料結構。

在正確使用的情況下,複雜度為 \(O(n^{1-\frac{1}{k}})\).

K-D Tree 的實現

建樹

隨機一維選擇最中間的點為當前子樹的根,每個節點維護當前點的座標,已經整個子樹的矩形座標。

Pink Rabbit 說隨機選維度沒什麼問題。

int rt, ID;
struct node{ int lc, rc, x[K], L[K], R[K]; } t[N];
inline bool cmp(const node &a, const node &b){ return a.x[ID] < b.x[ID]; }
inline void getedge(int x){
	lfo(i, 0, K) t[x].L[i] = t[x].R[i] = t[x].x[i];
	if(ls(x)) lfo(i, 0, K) Min(t[x].L[i], t[ls(x)].L[i]), Max(t[x].R[i], t[ls(x)].R[i]);
	if(rs(x)) lfo(i, 0, K) Min(t[x].L[i], t[rs(x)].L[i]), Max(t[x].R[i], t[rs(x)].R[i]);
}
void build(int &x, int l, int r){
	if(l > r) return;
	int mid = l + r >> 1; x = mid, ID = rand() % K;
	nth_element(t + l, t + mid, t + r + 1, cmp);
	build(ls(x), l, mid - 1), build(rs(x), mid + 1, r);
	getedge(x);
}

插入/刪除

  • 刪除比較簡單,直接標記為不存在即可,複雜度依然靠譜。
  • 插入比較麻煩,如果可離線的話,最好先建樹,否則考慮 \(\sqrt n\) 次插入操作後重構整棵樹。

K-D Tree 的應用

  • 求最近點對的騙分做法。

  • 在遞迴過程中,判斷是否繼續是:

    • 相交:繼續
    • 包含:打標記,return
    • 相離:return

    則複雜度靠譜。

    如:矩形覆蓋,單點查詢.