1. 程式人生 > >P4357 [CQOI2016]K遠點對(KDTree)

P4357 [CQOI2016]K遠點對(KDTree)

傳送門

又一次產生了KDTree本質就是爆搜的感覺……
大概就類似於p4169,只不過是從最近點對變成了第\(k\)遠點對
我們開一個小根堆,裡面放\(k\)個元素,起初全為\(0\),然後每一次都把點對的距離和堆頂比較,如果點對距離大於就彈出堆頂並讓這個點對入堆,那麼最後堆頂就是答案了
於是我們可以列舉每一個點,然後在KDTree上dfs就行了
然後因為每個點對會被列舉兩次,所以小根堆的大小實際上要開\(2*k\)

//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define inf 0x3f3f3f3f
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
ll read(){
    R ll res,f=1;R char ch;
    while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
    for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
    return res*f;
}
const int N=1e5+5;
struct node{ll v[2],mn[2],mx[2];int l,r;}tr[N],S;
int n,m,K,rt;priority_queue<ll,vector<ll>,greater<ll> >q;
inline bool operator <(const node &a,const node &b){return a.v[K]<b.v[K];}
void upd(int p){
    int l=tr[p].l,r=tr[p].r;
    fp(i,0,1){
        tr[p].mn[i]=tr[p].mx[i]=tr[p].v[i];
        if(l)cmin(tr[p].mn[i],tr[l].mn[i]),cmax(tr[p].mx[i],tr[l].mx[i]);
        if(r)cmin(tr[p].mn[i],tr[r].mn[i]),cmax(tr[p].mx[i],tr[r].mx[i]);
    }
}
int build(int l,int r,int k){
    K=k;int mid=(l+r)>>1;nth_element(tr+l,tr+mid,tr+r+1);
    if(l<mid)tr[mid].l=build(l,mid-1,k^1);
    if(mid<r)tr[mid].r=build(mid+1,r,k^1);
    upd(mid);return mid;
}
inline ll sqr(ll x){return x*x;}
inline ll ck(ll x,ll y,int p){
    return max(sqr(tr[p].mn[0]-x),sqr(tr[p].mx[0]-x))+max(sqr(tr[p].mn[1]-y),sqr(tr[p].mx[1]-y));
}
inline ll dis(ll x,ll y,ll xx,ll yy){
    return sqr(x-xx)+sqr(y-yy);
}
void query(int p){
    ll dl=-inf,dr=-inf,dd=dis(tr[p].v[0],tr[p].v[1],S.v[0],S.v[1]);
    if(tr[p].l)dl=ck(S.v[0],S.v[1],tr[p].l);
    if(tr[p].r)dr=ck(S.v[0],S.v[1],tr[p].r);
    if(dd>q.top())q.pop(),q.push(dd);
    if(dl>dr){
        if(dl>q.top())query(tr[p].l);
        if(dr>q.top())query(tr[p].r);
    }else{
        if(dr>q.top())query(tr[p].r);
        if(dl>q.top())query(tr[p].l);
    }
}
int main(){
//  freopen("testdata.in","r",stdin);
    n=read(),m=read();fp(i,1,n)tr[i].v[0]=read(),tr[i].v[1]=read();
    rt=build(1,n,0);fp(i,1,m*2)q.push(0);
    fp(i,1,n)S.v[0]=tr[i].v[0],S.v[1]=tr[i].v[1],query(rt);
    printf("%lld\n",q.top());return 0;
}