CQOI 2016 k远点对

题目大意:n个点,求第k远的点对的距离

KD树裸题

注意要用堆维护第k远

#include<bits/stdc++.h>
#define ll unsigned long long
#define maxn 100010
using namespace std;
inline int read(){
    int s=0;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar());
    for(;ch>='0'&&ch<='9';ch=getchar())s=s*10+ch-'0';
    return s;
}
int n,k,D,root;
struct node{
    ll d[2],mn[2],mx[2],ls,rs;
    node(int x=0,int y=0){d[0]=x;d[1]=y;}
    ll & operator [] (int x){return d[x];}
    friend bool operator < (node a,node b){return a[D]<b[D];}
}a[maxn];
struct K{
    ll d;
    K(ll a=0){d=a;}
};
priority_queue<K>Q;
bool operator < (K a,K b){return a.d>b.d;}
struct KD{
    node t[maxn],T;
    void up(int k){
        node l=t[t[k].ls],r=t[t[k].rs];
        for(int i=0;i<2;++i){
            t[k].mn[i]=t[k].mx[i]=t[k][i];
            if(t[k].ls)t[k].mn[i]=min(t[k].mn[i],l.mn[i]),t[k].mx[i]=max(t[k].mx[i],l.mx[i]);
            if(t[k].rs)t[k].mn[i]=min(t[k].mn[i],r.mn[i]),t[k].mx[i]=max(t[k].mx[i],r.mx[i]);
        }
    }
    int build(int l,int r,int now){
        D=now;int mid=(l+r)>>1;
        nth_element(a+l,a+mid,a+r+1);
        t[mid]=a[mid];
        if(l<mid)t[mid].ls=build(l,mid-1,now^1);
        if(r>mid)t[mid].rs=build(mid+1,r,now^1);
        up(mid);return mid;
    }
    ll dis(node a,node b){
        return (a[0]-b[0])*(a[0]-b[0])+(a[1]-b[1])*(a[1]-b[1]);
    }
    ll get(int k){
        if(!k)return 0;
        ll L=0;
        L=max(L,dis(T,node(t[k].mn[0],t[k].mn[1])));
        L=max(L,dis(T,node(t[k].mn[0],t[k].mx[1])));
        L=max(L,dis(T,node(t[k].mx[0],t[k].mn[1])));
        L=max(L,dis(T,node(t[k].mx[0],t[k].mx[1])));
        return L;
    }
    void ask(int k){
        if(!k)return;
        ll dl=get(t[k].ls),dr=get(t[k].rs);
        ll L=dis(T,t[k]);
        if(L>Q.top().d){Q.pop();Q.push(K(L));}
        if(dl>dr){
            if(dl>Q.top().d)ask(t[k].ls);
            if(dr>Q.top().d)ask(t[k].rs);
        }else{
            if(dr>Q.top().d)ask(t[k].rs);
            if(dl>Q.top().d)ask(t[k].ls);
        }
    }
    void work(){
        for(int i=1;i<=n;++i){
            T=a[i];
            ask(root);
        }
    }
}kd;
int main(){
    n=read();k=read();k<<=1;
    for(int i=1;i<=n;++i)
        a[i][0]=read(),a[i][1]=read();
    root=kd.build(1,n,0);
    for(int i=1;i<=k;++i)Q.push(K(0));
    kd.work();
    cout<<Q.top().d<<endl;
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/117208-/p/5382146.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值