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 98 99 100 101 102 103 104 105 106
| struct Point { int x, y; }; inline bool cmpx(Point fir, Point sec) { if (fir.x == sec.x) { return fir.y < sec.y; } return fir.x < sec.x; } inline bool cmpy(Point fir, Point sec) { if (fir.y == sec.y) { return fir.x < sec.x; } return fir.y < sec.y; } inline double distpp(Point a, Point b) { return sqrt((double)(a.x - b.x) * (a.x - b.x) + (double)(a.y - b.y) * (a.y - b.y)); }
struct Rect { int x1, x2, y1, y2; inline Rect operator+(const Rect sec) const { Rect ans; ans.x1 = min(x1, sec.x1); ans.x2 = max(x2, sec.x2); ans.y1 = min(y1, sec.y1); ans.y2 = max(y2, sec.y2); return ans; } }; inline double distpr(Point a, Rect b) { double ans = 0; if (a.x < b.x1) ans += (double)(a.x - b.x1) * (a.x - b.x1); if (a.x > b.x2) ans += (double)(a.x - b.x2) * (a.x - b.x2); if (a.y < b.y1) ans += (double)(a.y - b.y1) * (a.y - b.y1); if (a.y > b.y2) ans += (double)(a.y - b.y2) * (a.y - b.y2); return sqrt(ans); }
int n; Point a[MAXn + 10];
int root, ls[MAXn + 10], rs[MAXn + 10]; Rect area[MAXn + 10]; inline void pushup(int id) { area[id].x1 = area[id].x2 = a[id].x; area[id].y1 = area[id].y2 = a[id].y; if (ls[id]) area[id] = area[id] + area[ls[id]]; if (rs[id]) area[id] = area[id] + area[rs[id]]; } int Build(int l, int r) { if (l > r) return 0; int mid = (l + r) >> 1; double avx = 0, avy = 0, vax = 0, vay = 0; for (int i = l; i <= r; ++i) { avx += a[i].x; avy += a[i].y; } avx /= r - l + 1; avy /= r - l + 1; for (int i = l; i <= r; ++i) { vax += (a[i].x - avx) * (a[i].x - avx); vay += (a[i].y - avy) * (a[i].y - avy); } if (vax > vay) nth_element(a + l, a + mid, a + 1 + r, cmpx); else nth_element(a + l, a + mid, a + 1 + r, cmpy); ls[mid] = Build(l, mid - 1); rs[mid] = Build(mid + 1, r); pushup(mid); return mid; } double ans = INF; void query(int id, int idx) { if (id == 0) return; if (id != idx) ans = min(ans, distpp(a[id], a[idx])); double distls = distpr(a[idx], area[ls[id]]), distrs = distpr(a[idx], area[rs[id]]); if (distls < ans && distrs < ans) { if (distls < distrs) { query(ls[id], idx); if (distrs < ans) query(rs[id], idx); } else { query(rs[id], idx); if (distls < ans) query(ls[id], idx); } } else if (distls < ans) { query(ls[id], idx); } else if (distrs < ans) { query(rs[id], idx); } } void Solve() { for (int i = 1; i <= n; ++i) { query(root, i); } }
signed main() { read(n); for (int i = 1; i <= n; ++i) { read(a[i].x, a[i].y); } root = Build(1, n); Solve(); printf("%.4lf\n", ans); return 0; }
|