bzoj4520 [Cqoi2016]K远点对

Description

已知平面内 N 个点的坐标,求欧氏距离下的第 K 远点对。

Input

输入文件第一行为用空格隔开的两个整数 N, K。接下来 N 行,每行两个整数 X,Y,表示一个点
的坐标。1 < =  N < =  100000, 1 < =  K < =  100, K < =  N*(N−1)/2 , 0 < =  X, Y < 2^31。

Output

输出文件第一行为一个整数,表示第 K 远点对的距离的平方(一定是个整数)。

将所有点建成kd树,用堆维护当前已找到的前k大的点对距离,根据已知的第k大距离距离在kd树上搜索即可

#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#include<functional>
const long long inf=1ll<<62;
inline void mins(int&a,int b){if(a>b)a=b;}
inline void maxs(int&a,int b){if(a<b)a=b;}
inline void maxs(long long&a,long long b){if(a<b)a=b;}
inline int max(int a){return a>0?a:0;}
std::priority_queue<long long,std::vector<long long>,std::greater<long long> >mxs;
int n,k;
int X[2];
inline int read(){
    int x=0,c=getchar();
    while(c>57||c<48)c=getchar();
    while(c>47&&c<58)x=x*10+c-48,c=getchar();
    return x;
}
inline long long dis(long long x,long long y){
    return x*x+y*y;
}
inline void upds(long long x){
    if(x<mxs.top())return;
    mxs.pop();
    mxs.push(x);
}
struct node{
    int x[2],mn[2],mx[2];
    node*c[2],*f;
    inline void set(int x1,int x2){
        x[0]=mn[0]=mx[0]=x1;
        x[1]=mn[1]=mx[1]=x2;
    }
    inline void upd(){
        for(int i=0;i<2;i++)if(c[i]){
            for(int j=0;j<2;j++){
                mins(mn[j],c[i]->mn[j]);
                maxs(mx[j],c[i]->mx[j]);
            }
        }
    }
    inline long long maxv(){
        if(!this)return -1;
        return dis(max(X[0]-mn[0])|max(mx[0]-X[0]),max(X[1]-mn[1])|max(mx[1]-X[1]));
    }
    void getmax(){
        long long a1=-1,a2=-1;
        upds(dis(x[0]-X[0],x[1]-X[1]));
        maxs(a1,c[0]->maxv());
        maxs(a2,c[1]->maxv());
        if(a1>a2){
            if(a1>mxs.top())c[0]->getmax();
            if(a2>mxs.top())c[1]->getmax();
        }else{
            if(a2>mxs.top())c[1]->getmax();
            if(a1>mxs.top())c[0]->getmax();
        }
    }
}ns[100005],*rt;
int dx=0;
inline bool operator<(const node&a,const node&b){
    if(a.x[dx]!=b.x[dx])return a.x[dx]<b.x[dx];
    return a.x[dx^1]<b.x[dx^1];
}
node*build(node*l,node*r){
    if(l==r)return 0;
    node*m=l+(r-l>>1);
    std::nth_element(l,m,r);
    dx^=1;
    m->c[0]=build(l,m);
    m->c[1]=build(m+1,r);
    m->upd();
    dx^=1;
    return m;
}
int main(){
    n=read();k=read()*2;
    for(int i=0;i<k;i++)mxs.push(0);
    for(int i=0;i<n;i++)ns[i].set(read(),read());
    rt=build(ns,ns+n);
    for(int i=0;i<n;i++){
        X[0]=ns[i].x[0];
        X[1]=ns[i].x[1];
        rt->getmax();
    }
    printf("%lld",mxs.top());
    return 0;
} 

复杂度不易计算但实际运行效果很好

原文地址:https://www.cnblogs.com/ccz181078/p/5399680.html