KDT

后言

  • 除了每次操作,轮换维度之外,还有一种基于方差的写法
  • 我们求出所有维度的方差,找到方差大的也就是混乱的维度进行划分
  • nth_element(begin,pos,end,cmp); 这个背下来吧就
#include <bits/stdc++.h>
using namespace std;
// typedef double db;
// typedef long double ldb;
typedef long long db;
typedef __int128 ldb;
struct D { db v, mi, ma; };
struct P { db x, y; };
const int N = 400500;
template<class T>
constexpr T pow(T x) { return x * x; }
struct node
{
    int ls, rs; D x, y;
    db MinDis(P p)
    {
        db sum = 0;
        if (p.x < x.mi)sum += pow(p.x - x.mi);
        if (p.x > x.ma)sum += pow(p.x - x.ma);
        if (p.y < y.mi)sum += pow(p.y - y.mi);
        if (p.y > y.ma)sum += pow(p.y - y.ma);
        return sum;
    }
    db Dis(P p) { return pow(x.v - p.x) + pow(y.v - p.y); }
};
node t[N];
void Min(db& a, db b) { if (a > b)a = b; }
void Max(db& a, db b) { if (a < b)a = b; }
void up(int id)
{
    node& x = t[id], & ls = t[t[id].ls], & rs = t[t[id].rs];
    x.x.mi = x.x.ma = x.x.v; x.y.mi = x.y.ma = x.y.v;
    if (x.ls)Min(x.x.mi, ls.x.mi), Max(x.x.ma, ls.x.ma), Min(x.y.mi, ls.y.mi), Max(x.y.ma, ls.y.ma);
    if (x.rs)Min(x.x.mi, rs.x.mi), Max(x.x.ma, rs.x.ma), Min(x.y.mi, rs.y.mi), Max(x.y.ma, rs.y.ma);
}
P a[N]; int idx = 0;
bool check(int l, int r)
{
    long double sx = 0, sy = 0, xf = 0, yf = 0;
    for (int i = l;i <= r;i++)xf += a[i].x, yf += a[i].y;
    xf /= (r - l + 1); yf /= (r - l + 1);
    for (int i = l;i <= r;i++)sx += pow(xf - a[i].x), sy += pow(yf - a[i].y);
    return sx > sy;
}
bool cmpx(const P& a, const P& b) { return a.x < b.x; };
bool cmpy(const P& a, const P& b) { return a.y < b.y; };
int build(int l, int r)
{
    if (r < l)return 0;
    int m = l + r >> 1, n = ++idx;
    nth_element(a + l, a + m, a + r + 1, check(l, r) ? cmpx : cmpy);
    t[n].x.v = a[m].x;t[n].y.v = a[m].y;
    t[n].ls = build(l, m - 1);t[n].rs = build(m + 1, r);
    return up(n), n;
}
int id[N], now; P np; db mi = 4e18;
void ask(int x)
{
    if (!x)return; if (x != now) Min(mi, t[x].Dis(np));
    db l = t[t[x].ls].MinDis(np), r = t[t[x].rs].MinDis(np);
    if (l < r) { if (l < mi)ask(t[x].ls);if (r < mi)ask(t[x].rs); }
    else { if (r < mi)ask(t[x].rs);if (l < mi)ask(t[x].ls); }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr); cout.tie(nullptr);
    int n, rt; cin >> n;
    for (int i = 1;i <= n;i++) cin >> a[i].x >> a[i].y, id[i] = i;
    rt = build(1, n);// random_shuffle(id + 1, id + 1 + n);
    for (int i = 1;i <= n;i++)
        now = id[i], np = { t[now].x.v,t[now].y.v }, ask(rt);
    cout << mi << '\n';
    // cout << std::fixed << std::setprecision(4) << sqrt(mi) << '\n';
    return 0;
}
posted @ 2025-04-23 08:01  LUHCUH  阅读(28)  评论(0)    收藏  举报