hdu 2966 In case of failure k-d树

题目链接

 

给n个点, 求出每个点到离它最近的点的距离。

 

直接建k-d树然后查询就可以  感觉十分神奇...

明白了算法原理但是感觉代码还不是很懂...

#include <bits/stdc++.h>
using namespace std;
#define pb(x) push_back(x)
#define ll long long
#define mk(x, y) make_pair(x, y)
#define lson l, m, rt<<1
#define mem(a) memset(a, 0, sizeof(a))
#define rson m+1, r, rt<<1|1
#define mem1(a) memset(a, -1, sizeof(a))
#define mem2(a) memset(a, 0x3f, sizeof(a))
#define rep(i, n, a) for(int i = a; i<n; i++)
#define fi first
#define se second
typedef complex <double> cmx;
typedef pair<int, int> pll;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int mod = 1e9+7;
const int inf = 1061109567;
const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
struct node
{
    int p[2];
    int l, r, idx;
    int operator [] (const int& idx)const
    {
        return p[idx];
    }
}a[100005];
int cmpflag, idx[100005];
ll ans;
bool cmp(const node& x, const node& y)
{
    return x[cmpflag] < y[cmpflag];
}
int build(int l, int r, int flag)
{
    int mid = l + r >> 1;
    cmpflag = flag;
    nth_element(a+l, a+mid, a+r+1, cmp);
    idx[a[mid].idx] = mid;
    a[mid].l = (l != mid)?build(l, mid - 1, !flag):0;
    a[mid].r = (r != mid)?build(mid + 1, r, !flag):0;
    return mid;
}
ll dis(ll x, ll y = 0)
{
    return x * x + y * y;
}
ll query(int rt, int flag, int x, int y)
{
    ll tmp = dis(x - a[rt][0], y - a[rt][1]);
    if(tmp) {
        ans = min(ans, tmp);
    }
    if(a[rt].l && a[rt].r) {
        bool d = !flag ? (x <= a[rt][0]) : (y <= a[rt][1]);
        ll dist = !flag ? dis(x - a[rt][0]) : dis(y - a[rt][1]);
        query(d?a[rt].l:a[rt].r, !flag, x, y);
        if(dist < ans) {
            query(!d?a[rt].l:a[rt].r, !flag, x, y);
        }
    } else if(a[rt].l) {
        query(a[rt].l, !flag, x, y);
    } else if(a[rt].r) {
        query(a[rt].r, !flag, x, y);
    }
}
int main()
{
    int t, n;
    cin>>t;
    while(t--) {
        cin>>n;
        for(int i = 1; i <= n; i++) {
            scanf("%d%d", &a[i].p[0], &a[i].p[1]);
            a[i].idx = i;
        }
        int root = build(1, n, 0);
        for(int i = 1; i <= n; i++) {
            ans = 1e18;
            query(root, 0, a[idx[i]][0], a[idx[i]][1]);
            printf("%lld\n", ans);
        }
    }
    return 0;
}

 

posted on 2016-10-21 22:50  yohaha  阅读(150)  评论(0编辑  收藏  举报

导航