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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
| // 더 많은 정보는 42jerrykim.github.io 에서 확인하세요.
#include <bits/stdc++.h>
using namespace std;
struct Point {
int x;
int y;
};
static inline long long squaredDistance(const Point& a, const Point& b) {
long long dx = static_cast<long long>(a.x) - static_cast<long long>(b.x);
long long dy = static_cast<long long>(a.y) - static_cast<long long>(b.y);
return dx * dx + dy * dy;
}
// Recursively computes the closest pair distance squared on points[l, r),
// assuming points are sorted by x. As a side effect, points[l, r) will be
// sorted by y when the function returns.
long long closestPairRec(vector<Point>& points, vector<Point>& buffer, int l, int r) {
int count = r - l;
if (count <= 3) {
long long best = LLONG_MAX;
for (int i = l; i < r; ++i) {
for (int j = i + 1; j < r; ++j) {
best = min(best, squaredDistance(points[i], points[j]));
}
}
sort(points.begin() + l, points.begin() + r, [](const Point& a, const Point& b) {
if (a.y != b.y) return a.y < b.y;
return a.x < b.x;
});
return best;
}
int mid = (l + r) / 2;
int midX = points[mid].x;
long long dLeft = closestPairRec(points, buffer, l, mid);
long long dRight = closestPairRec(points, buffer, mid, r);
long long d = min(dLeft, dRight);
// Merge by y to keep points[l, r) sorted by y
int i = l, j = mid, k = l;
while (i < mid && j < r) {
if (points[i].y < points[j].y || (points[i].y == points[j].y && points[i].x <= points[j].x)) {
buffer[k++] = points[i++];
} else {
buffer[k++] = points[j++];
}
}
while (i < mid) buffer[k++] = points[i++];
while (j < r) buffer[k++] = points[j++];
for (int t = l; t < r; ++t) points[t] = buffer[t];
// Build strip: points within sqrt(d) in x from the dividing line, strip already sorted by y
static vector<Point> strip;
strip.clear();
strip.reserve(r - l);
for (int t = l; t < r; ++t) {
long long dx = static_cast<long long>(points[t].x) - midX;
if (dx * dx < d) strip.push_back(points[t]);
}
// Compare each point with subsequent points whose y-distance is < sqrt(d)
for (size_t a = 0; a < strip.size(); ++a) {
for (size_t b = a + 1; b < strip.size(); ++b) {
long long dy = static_cast<long long>(strip[b].y) - strip[a].y;
if (dy * dy >= d) break; // y too far; later points will be even farther in y
d = min(d, squaredDistance(strip[a], strip[b]));
}
}
return d;
}
long long closestPair(vector<Point>& points) {
sort(points.begin(), points.end(), [](const Point& a, const Point& b) {
if (a.x != b.x) return a.x < b.x;
return a.y < b.y;
});
vector<Point> buffer(points.size());
return closestPairRec(points, buffer, 0, static_cast<int>(points.size()));
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
if (!(cin >> n)) return 0;
vector<Point> points(n);
for (int i = 0; i < n; ++i) {
cin >> points[i].x >> points[i].y;
}
cout << closestPair(points) << '\n';
return 0;
}
|