TIOJ-1500

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
/*
-------------- | /
| | /
| | /
| * |/ | | ------ *
| | | | / \
| | |\ | | | |\ |
\ | | | \ | | | | \ |
\ | | | \ | | \ / \ |
V | | \ \__/| ----- \ |
*/
#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;
}