题目:传送门
题意:给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的
2≤n≤200000
思路:
截取自洛谷题解的 -> 戳
#include <bits/stdc++.h> #define LL long long #define mem(i, j) memset(i, j, sizeof(i)) #define rep(i, j, k) for(int i = j; i <= k; i++) #define dep(i, j, k) for(int i = k; i >= j; i--) #define pb push_back #define make make_pair #define INF INT_MAX #define inf LLONG_MAX #define PI acos(-1) #define fir first #define sec second using namespace std; const int N = 2e5 + 5; const double eps = 1e-8; struct Point { double x, y; Point(double x = 0, double y = 0) : x(x), y(y) { } }; int dcmp(double x) { if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1; } Point operator + (Point A, Point B) { return Point(A.x + B.x, A.y + B.y); } Point operator - (Point A, Point B) { return Point(A.x - B.x, A.y - B.y); } Point operator * (Point A, double p) { return Point(A.x * p, A.y * p); } Point operator / (Point A, double p) { return Point(A.x / p, A.y / p); } bool cmp2(Point A, Point B) { return dcmp(A.y - B.y) < 0; } bool cmp1(Point A, Point B) { return dcmp(A.x - B.x) == 0 ? dcmp(A.y - B.y) < 0 : dcmp(A.x - B.x) < 0; } Point P[N], tmp[N]; double Dis(Point A, Point B) { return sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y)); } double solve(int l, int r) { if(l == r) return 1e20; if(l + 1 == r) return Dis(P[l], P[r]); int mid = (l + r) >> 1; double dis1 = solve(l, mid); double dis2 = solve(mid + 1, r); double dis = min(dis1, dis2); int tot = 0; rep(i, l, r) { if(fabs(P[mid].x - P[i].x) <= dis) tmp[++tot] = P[i]; } sort(tmp + 1, tmp + 1 + tot, cmp2); rep(i, 1, tot) rep(j, i + 1, tot) { if(tmp[j].y - tmp[i].y > dis) break; dis = min(dis, Dis(tmp[i], tmp[j])); } return dis; } int main() { int n; scanf("%d", &n); rep(i, 1, n) scanf("%lf %lf", &P[i].x, &P[i].y); sort(P + 1, P + 1 + n, cmp1); printf("%.4f ", solve(1, n)); return 0; }