KD-tree裸题切切,人生有什么希望
找最远点对只要记录最大值,同样,找k远点对只要维护当前前k大值,每次和第k大比较即可。
//听说加const会变快?@lych_cys
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#define ll long long
#define N 100005
#define inf 1000000000
using namespace std;
int n,k,Rt,Q[2],D;
struct KD_node{int d[2],Mx[2],Mn[2],ls,rs;}T[N];
priority_queue<ll,vector<ll>,greater<ll> >q;
void Max(int &x,const int &y){if(x<y)x=y;}
void Min(int &x,const int &y){if(x>y)x=y;}
ll sqr(const int &x){return (ll)x*x;}
bool cmp(const KD_node &x,const KD_node &y){return x.d[D]<y.d[D];}
void update(int k)
{
int l=T[k].ls,r=T[k].rs;
for (int i=0;i<2;i++)
{
if (l) Max(T[k].Mx[i],T[l].Mx[i]),Min(T[k].Mn[i],T[l].Mn[i]);
if (r) Max(T[k].Mx[i],T[r].Mx[i]),Min(T[k].Mn[i],T[r].Mn[i]);
}
}
void build(int &k,int l,int r,int now)
{
int mid=(l+r)>>1;D=now;k=mid;
nth_element(T+l,T+mid,T+r+1,cmp);
for (int i=0;i<2;i++)
T[k].Mx[i]=T[k].Mn[i]=T[k].d[i];
if (l<mid) build(T[k].ls,l,mid-1,now^1);
if (r>mid) build(T[k].rs,mid+1,r,now^1);
update(k);
}
ll ask(int k)
{
if (!k) return 0;
return max(sqr(T[k].Mn[0]-Q[0]),sqr(T[k].Mx[0]-Q[0]))+
max(sqr(T[k].Mn[1]-Q[1]),sqr(T[k].Mx[1]-Q[1]));
}
void qry(int k)
{
ll dis=sqr(T[k].d[0]-Q[0])+sqr(T[k].d[1]-Q[1]);
if (dis>q.top()) q.pop(),q.push(dis);
ll Dl=ask(T[k].ls),Dr=ask(T[k].rs);
if (Dl>Dr)
{
if (Dl>q.top()) qry(T[k].ls);
if (Dr>q.top()) qry(T[k].rs);
}
else
{
if (Dr>q.top()) qry(T[k].rs);
if (Dl>q.top()) qry(T[k].ls);
}
}
int main()
{
scanf("%d%d",&n,&k);
for (int i=1;i<=n;i++)
scanf("%d%d",&T[i].d[0],&T[i].d[1]);
build(Rt,1,n,0);
for (int i=1;i<=2*k;i++)q.push(0);
for (int i=1;i<=n;i++)
Q[0]=T[i].d[0],Q[1]=T[i].d[1],qry(Rt);
printf("%lld\n",q.top());
return 0;
}