cf 429D Tricky Function - 平面最近點對
阿新 • • 發佈:2020-08-23
傳送門
平面最近點對模型
給出平面上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; }