平面 n (≤500,000) 個點,曼哈頓距離。對每個點,求其到所有點的最遠距離與最近距離之差的最小值。
x0,x1,y0,y1(最小/最大坐標)// 最小可能曼哈頓距離
int disMin(Point p) {
int d=0;
if (p.x < x0) d += x0 - p.x;
if (p.x > x1) d += p.x - x1;
if (p.y < y0) d += y0 - p.y;
if (p.y > y1) d += p.y - y1;
return d;
}
// 最大可能曼哈頓距離
int disMax(Point p) {
return max(abs(p.x-x0), abs(p.x-x1)) + max(abs(p.y-y0), abs(p.y-y1));
}
遞歸遍歷 KD-Tree,維護全局 _min, _max。優先搜索更有希望的子樹(最小距離搜索 disMin 小的先搜;最大距離搜索 disMax 大的先搜),剪枝條件:子樹估算值無法優於當前最優值則放棄。
struct KDNode {
Point pt; KDNode *ch[2];
int x0,y0,x1,y1;
KDNode(Point p): pt(p), ch{nullptr,nullptr}, x0(p.x),y0(p.y),x1(p.x),y1(p.y) {}
void maintain() {
for (int d=0; d<2; ++d) if (ch[d]) {
x0=min(x0,ch[d]->x0); x1=max(x1,ch[d]->x1);
y0=min(y0,ch[d]->y0); y1=max(y1,ch[d]->y1);
}
}
};
KDNode* build(vector& pts, int l, int r, int dim) {
if (l>r) return nullptr;
int mid=(l+r)/2;
nth_element(pts.begin()+l, pts.begin()+mid, pts.begin()+r+1,
[dim](Point a, Point b){ return dim? a.xch[0] = build(pts, l, mid-1, dim^1);
node->ch[1] = build(pts, mid+1, r, dim^1);
node->maintain();
return node;
}
void queryMin(KDNode* node, Point p, int& best) {
if (!node) return;
best = min(best, abs(node->pt.x-p.x)+abs(node->pt.y-p.y));
int dl = node->ch[0] ? node->ch[0]->disMin(p) : INT_MAX;
int dr = node->ch[1] ? node->ch[1]->disMin(p) : INT_MAX;
if (dl < dr) {
if (dl <= best) queryMin(node->ch[0], p, best);
if (dr <= best) queryMin(node->ch[1], p, best);
} else {
if (dr <= best) queryMin(node->ch[1], p, best);
if (dl <= best) queryMin(node->ch[0], p, best);
}
}
// queryMax 類似,用 disMax 且取 max
nth_element O(n) 找中位數,構建總時間 O(n log n)KD-Tree 是高維最近鄰搜索的經典數據結構,掌握其構建、邊界維護、剪枝查詢三大核心模塊,可解決大規模幾何最近/最遠鄰問題。