-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathKD_Tree.cpp
81 lines (80 loc) · 2.22 KB
/
KD_Tree.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
const int MXN = 100005;
struct KDTree {
struct Node {
int x,y,x1,y1,x2,y2;
int id,f;
Node *L, *R;
}tree[MXN];
int n;
Node *root;
LL dis2(int x1, int y1, int x2, int y2) {
LL dx = x1-x2;
LL dy = y1-y2;
return dx*dx+dy*dy;
}
static bool cmpx(Node& a, Node& b){ return a.x<b.x; }
static bool cmpy(Node& a, Node& b){ return a.y<b.y; }
void init(vector<pair<int,int>> ip) {
n = ip.size();
for (int i=0; i<n; i++) {
tree[i].id = i;
tree[i].x = ip[i].first;
tree[i].y = ip[i].second;
}
root = build_tree(0, n-1, 0);
}
Node* build_tree(int L, int R, int dep) {
if (L>R) return nullptr;
int M = (L+R)/2;
tree[M].f = dep%2;
nth_element(tree+L, tree+M, tree+R+1, tree[M].f ? cmpy : cmpx);
tree[M].x1 = tree[M].x2 = tree[M].x;
tree[M].y1 = tree[M].y2 = tree[M].y;
tree[M].L = build_tree(L, M-1, dep+1);
if (tree[M].L) {
tree[M].x1 = min(tree[M].x1, tree[M].L->x1);
tree[M].x2 = max(tree[M].x2, tree[M].L->x2);
tree[M].y1 = min(tree[M].y1, tree[M].L->y1);
tree[M].y2 = max(tree[M].y2, tree[M].L->y2);
}
tree[M].R = build_tree(M+1, R, dep+1);
if (tree[M].R) {
tree[M].x1 = min(tree[M].x1, tree[M].R->x1);
tree[M].x2 = max(tree[M].x2, tree[M].R->x2);
tree[M].y1 = min(tree[M].y1, tree[M].R->y1);
tree[M].y2 = max(tree[M].y2, tree[M].R->y2);
}
return tree+M;
}
int touch(Node* r, int x, int y, LL d2){
LL dis = sqrt(d2)+1;
if (x<r->x1-dis || x>r->x2+dis ||
y<r->y1-dis || y>r->y2+dis)
return 0;
return 1;
}
void nearest(Node* r, int x, int y,
int &mID, LL &md2){
if (!r || !touch(r, x, y, md2)) return;
LL d2 = dis2(r->x, r->y, x, y);
if (d2 < md2 || (d2 == md2 && mID < r->id)) {
mID = r->id;
md2 = d2;
}
// search order depends on split dim
if ((r->f == 0 && x < r->x) ||
(r->f == 1 && y < r->y)) {
nearest(r->L, x, y, mID, md2);
nearest(r->R, x, y, mID, md2);
} else {
nearest(r->R, x, y, mID, md2);
nearest(r->L, x, y, mID, md2);
}
}
int query(int x, int y) {
int id = 1029384756;
LL d2 = 102938475612345678LL;
nearest(root, x, y, id, d2);
return id;
}
}tree;