It’s perfectly normal, nothing wrong with me But we’re going to need a clean up on aisle 3 And now I’m posed in an awkward stance because I 據說有位顧客,因為超商的動線設計不良,不小心把東西翻倒在褲子上,使得他要去第三排走廊清理一下。之後超商在檢討為什麼會發生這種事情,他們發現若有兩兩障礙物離太近就會有奇怪的顧客,故意從兩障礙的夾縫中走過去,就會發生意外。 你就是那位奇怪的顧客,你想知道兩障礙物最近的距離是多少。好穿越最近的夾縫獲得成就感。
$N<50000$
刷講義D&C部分刷到的 一開始還以為跟逆序數對一樣能砸資結解決 不過我想不到>< 先根據$x$座標排序 分割問題當只有兩點時可以直接更新答案 其餘的合併就是找左半邊最右邊的點的$x$的左右$ans$範圍內的點 然後因為每點之間的距離肯定$\geq ans$ 因此只要找最多三個點就好了 複雜度 $O(nlog^2n)$
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 #include <bits/stdc++.h> using namespace std;#define EmiliaMyWife ios::sync_with_stdio(0); cin.tie(NULL); #define F first #define S second #define pb push_back #define all(a) (a).begin(), (a).end() typedef int64_t ll;typedef pair<ll, ll> pll;const ll LINF = 4611686018427387903 ;double ans;vector<pll> arr; bool cmp (pll a, pll b) { return (a.S<b.S); } double getD (pll a, pll b) { return sqrt (double (a.F-b.F)*(a.F-b.F)+double (a.S-b.S)*(a.S-b.S)); } void getAns (int l, int r) { if (l>=r) return ; if (l==r-1 ) { ans=min (ans, getD (arr[l], arr[r])); return ; } int m = (l+r)/2 ; getAns (l, m); getAns (m+1 , r); vector<pll> aw, bw; for (int i = m; i>=l; i--) { if (arr[m].F-arr[i].F > ans) break ; aw.pb (arr[i]); } for (int i = m+1 ; i<=r; i++) { if (arr[i].F-arr[m].F>ans) break ; bw.pb (arr[i]); } sort (all (aw), cmp); sort (all (bw), cmp); int b=0 ; if (bw.empty ()) return ; for (int i = 0 ; i < aw.size (); i++) { while (b+1 <bw.size () && bw[b].S<aw[i].S) b++; for (int x = max (0 , b-2 ); x <= b; x++) ans=min (ans, getD (aw[i], bw[x])); } } signed main () { EmiliaMyWife cout << fixed << setprecision (6 ); int n; while (cin >> n) { arr.clear (); arr.resize (n); ans=LINF; for (int i = 0 ; i < n; i++) cin >> arr[i].F >> arr[i].S; sort (all (arr)); getAns (0 , n-1 ); cout << ans << '\n' ; } return 0 ; }