首页 > 其他 > 详细

cf 429D Tricky Function - 平面最近点对

时间:2020-08-22 20:06:25      阅读:68      评论:0      收藏:0      [点我收藏+]

平面最近点对模型
给出平面上n个点,找出其中一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的
分治法求
\(g(i,j)\)就是求区间[i + 1, j]的区间的值,也就是前缀和表示\(sum[j] - sum[i]\)
那么转换为\((j - i) ^ 2 + (sum[j] - sum[i]) ^ 2\)
那么对于n个点,x就是i,y就是前缀和

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#define ll long long
using namespace std;
const int N = 1e6 + 5;
const ll Inf = 1e13;
struct Point {
    ll x, y;
    Point (int X = 0, int Y = 0) { x = X, y = Y;}
} p[N], Q[N];
int tot = 0;
bool cmpx(Point a, Point b) {return a.x < b.x || (a.x == b.x && a.y < b.y);}
bool cmpy(Point a, Point b) {return a.y < b.y;}
ll dis(Point a, Point b) {
    return pow(a.x - b.x, 2) + pow(a.y - b.y, 2);
}
ll Merge(int l, int r) {
    ll ans = Inf;
    if (l == r) return ans;
    if (l + 1 == r) return dis(p[l], p[r]);
    int mid = (l + r) / 2;
    ll d1 = Merge(l, mid);
    ll d2 = Merge(mid + 1, r);
    ans = min(d1, d2);
    ll d = sqrt(ans);
    int k = 0;
    for (int i = mid; i >= l; i --) {
        if (p[mid].x - p[i].x > d) break;
        Q[++k] = p[i];
    }
    for (int i = mid + 1; i <= r; i ++) {
        if (p[i].x - p[mid].x > d) break;
        Q[++k] = p[i];
    }
    sort(Q + 1, Q + k + 1, cmpy);
    for (int i = 1; i < k; i ++) {
        for (int j = i + 1 ; j <= k && Q[j].y - Q[i].y <= d; j ++) {
            tot++; ans = min(ans, dis(Q[i], Q[j]));
        }
    }
    return ans;
}
int main() {
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        scanf("%lld%lld", &p[i].x, &p[i].y);
    }
    sort(p + 1, p + n + 1, cmpx);
    printf("%lld\n", Merge(1, n));
    return 0;
}

cf 429D Tricky Function - 平面最近点对

原文:https://www.cnblogs.com/Emcikem/p/13546784.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!