loj2043 「CQOI2016」K 远点对

k-d tree 裸题………………

#include <algorithm>
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
int n, k, rot, nowD, din;
ll dui[205];
const ll oo=9e18;
struct Point{
    int d[2], mn[2], mx[2], l, r;
    int & operator[](int x){
        return d[x];
    }
    bool operator<(const Point &x)const{
        return d[nowD]<x.d[nowD];
    }
}p[100005], T;
bool cmp(ll x, ll y){
    return x>y;
}
struct KDTree{
    Point t[100005];
    void pushUp(int k){
        int l=t[k].l, r=t[k].r;
        for(int i=0; i<2; i++){
            t[k].mn[i] = t[k].mx[i] = t[k][i];
            if(l){
                t[k].mn[i] = min(t[k].mn[i], t[l].mn[i]);
                t[k].mx[i] = max(t[k].mx[i], t[l].mx[i]);
            }
            if(r){
                t[k].mn[i] = min(t[k].mn[i], t[r].mn[i]);
                t[k].mx[i] = max(t[k].mx[i], t[r].mx[i]);
            }
        }
    }
    int build(int l, int r, int now){
        nowD = now;
        int mid=(l+r)>>1;
        nth_element(p+l, p+mid, p+r+1);
        t[mid] = p[mid];
        if(l<mid)   t[mid].l = build(l, mid-1, now^1);
        if(mid<r)   t[mid].r = build(mid+1, r, now^1);
        pushUp(mid);
        return mid;
    }
    ll getDis(const Point &u, const Point &v){
        return (ll)(u.d[1]-v.d[1])*(u.d[1]-v.d[1])+(ll)(u.d[0]-v.d[0])*(u.d[0]-v.d[0]);
    }
    ll simDis(int k){
        ll re=0;
        for(int i=0; i<2; i++){
            ll tmp=max(abs(t[k].mn[i]-T[i]), abs(t[k].mx[i]-T[i]));
            re += tmp * tmp;
        }
        return re;
    }
    void query(int k){
        ll d=getDis(t[k], T), disl=-oo, disr=-oo;
        int l=t[k].l, r=t[k].r;
        if(d>dui[1]){
            pop_heap(dui+1, dui+1+din, cmp);
            dui[din] = d;
            push_heap(dui+1, dui+1+din, cmp);
        }
        if(l)   disl = simDis(l);
        if(r)   disr = simDis(r);
        if(disl>disr){
            if(disl>dui[1]) query(l);
            if(disr>dui[1]) query(r);
        }
        else{
            if(disr>dui[1]) query(r);
            if(disl>dui[1]) query(l);   
        }
    }
}kdt;
int main(){
    cin>>n>>k;
    k *= 2;
    for(int i=1; i<=n; i++)
        scanf("%d %d", &p[i][0], &p[i][1]);
    rot = kdt.build(1, n, 0);
    while(k--)  dui[++din] = -oo;
    for(int i=1; i<=n; i++){
        T = p[i];
        kdt.query(rot);
    }
    cout<<dui[1]<<endl;
    return 0;
}

转载于:https://www.cnblogs.com/poorpool/p/8952624.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值