平面最近点对 141 分求助

P7883 平面最近点对(加强加强版)

mushezi @ 2023-04-09 12:06:38

#include <bits/stdc++.h>
using namespace std;

const int N = 4e5 + 5;
typedef long long ll;

struct point{
    ll x, y;
    bool operator < (const point & t) const {
        if(x == t.x) return y < t.y;
        return x < t.x;
    }
} mp[N], temp[N];
int n, a, b;

ll dist(point a, point b){
    return (ll)((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
}

ll solve(int l, int r){
    if(l == r) return 8e15;
    auto mid = (l + r) >> 1;
    auto d = min(solve(l, mid), solve(mid + 1, r));
    auto cur = mp[mid];
    ll ld = sqrt(d);

    {
        int i = l, j = mid + 1, cnt = 0;
        while(i <= mid && j <= r){
            if(mp[i].y < mp[j].y) temp[++cnt] = mp[i++];
            else temp[++cnt] = mp[j++];
        }
        while(i <= mid) temp[++cnt] = mp[i++];
        while(j <= r) temp[++cnt] = mp[j++];
        for(int k = 1; k <= cnt; k++){
            mp[l + k - 1] = temp[k];
        }
    }

    auto cnt = 0;
    for(int i = l; i <= r; i++){
        if(abs(mp[i].x - cur.x) <= ld){
            temp[++cnt] = mp[i];
        } 
    }

    for(int i = 1; i < cnt; i++){
        for(int j = i + 1; j <= cnt && abs(temp[j].y - temp[i].y) <= ld; j++){
            d = min(d, dist(temp[i], temp[j]));
            ld = sqrt(d);
        }
    }

    return d;
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);

    cin >> n;
    for(int i = 1; i <= n; i++){
        cin >> a >> b;
        mp[i] = {a, b};
    }

    sort(mp + 1, mp + n + 1);

    cout << solve(1, n);

    return 0;
}

|