[筆記] K-D Tree
阿新 • • 發佈:2022-02-16
一種可以 高效處理 \(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
則複雜度靠譜。
如:矩形覆蓋,單點查詢.