LuoguP4357 [CQOI2016]K远点对

kd-tree

#include<bits/stdc++.h>
#define lc (ch[x][0])
#define rc (ch[x][1])
#define ll long long
using namespace std;
const int maxn=1e6+4;
int n,m,cnt;
ll mn[maxn][2],mx[maxn][2],ch[maxn][2],sz[maxn];
int nthdir;
priority_queue<ll,vector<ll>,greater<ll> >q;
inline ll sq(ll x){
    return (ll)x*x;
}
struct Point{
    ll pos[2];
    ll& operator [](ll x){
        return pos[x];
    }
    bool operator < (const Point &t) const {
        return pos[nthdir] < t.pos[nthdir];
    }
    ll operator - (const Point &t) const {
        return sq(abs(pos[0]-t.pos[0]))+sq(abs(pos[1]-t.pos[1]));
    }
    Point(int x,int y){
        pos[0]=x;pos[1]=y;
    }
    Point(){};
}p[maxn];
inline void pushup(int x){
    for(int i=0;i<=1;i++){
        mn[x][i]=mx[x][i]=p[x][i];
        if(lc){
            mn[x][i]=min(mn[x][i],mn[lc][i]);
            mx[x][i]=max(mx[x][i],mx[lc][i]);
        }
        if(rc){
            mn[x][i]=min(mn[x][i],mn[rc][i]);
            mx[x][i]=max(mx[x][i],mx[rc][i]);
        }
    }
    sz[x]=sz[lc]+sz[rc]+1;
}
inline int build(int l,int r,int dir){
    nthdir=dir;
    int x=(l+r)>>1;
    nth_element(p+l,p+x,p+r+1);
    mn[x][0]=mx[x][0]=p[x][0];
    mn[x][1]=mx[x][1]=p[x][1];
    if(l<x) lc=build(l,x-1,dir^1);
    if(r>x) rc=build(x+1,r,dir^1);
    pushup(x);return x;
}
inline void insert(int x,Point P,int dir){
    if(P[dir]<p[x][dir]){
        if(lc) insert(lc,P,dir^1);
        else{
            lc=++cnt;p[cnt]=P;
            mn[cnt][0]=mx[cnt][0]=P[0];
            mn[cnt][1]=mx[cnt][1]=P[1];
        }
    }else{
        if(rc) insert(rc,P,dir^1);
        else{
            rc=++cnt;p[cnt]=P;
            mn[cnt][0]=mx[cnt][0]=P[0];
            mn[cnt][1]=mx[cnt][1]=P[1];
        }
    }
    pushup(x);
}
inline ll calc(int x,Point P){
    return max(sq(mn[x][0]-P[0]),sq(mx[x][0]-P[0]))+max(sq(mn[x][1]-P[1]),sq(mx[x][1]-P[1]));
}
inline void query(int x,Point P){
    ll h=P-p[x];
    if(h>q.top()){
        q.pop();
        q.push(h);
    }
    ll l=0,r=0;
    if(lc) l=calc(lc,P);
    if(rc) r=calc(rc,P);
    if(l>r){
        if(l>q.top()) query(lc,P);
        if(r>q.top()) query(rc,P);
    }else{
        if(r>q.top()) query(rc,P);
        if(l>q.top()) query(lc,P);
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d%d",&p[i][0],&p[i][1]);
    cnt=n;
    int rt=build(1,n,0);
    for(int i=1;i<=m*2;i++) q.push(0);
    for(int i=1;i<=n;i++){
        query(rt,p[i]);
    }
    cout<<q.top();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wifimonster/p/10509898.html
今日推荐