https://www.lydsy.com/JudgeOnline/problem.php?id=4520
查询第k远点对的欧几里得距离,由于重复,所以要记录前2k对
估价函数就是两维最大差值的平方之和还要比最大的2k个中最小的小的话,就不仅进入该子树。
进入子树的顺序因为是最远点对,所以优先进相反边,更容易找到更大的。
#include<bits/stdc++.h>
using namespace std;
const int maxl=1e5+10;
int n,k,idx,cnt,tot,root;
long long ans[maxl];
struct point
{
int x[2],val;
bool operator < (const point &b)const
{
return x[idx]<b.x[idx];
}
}a[maxl],b[maxl];
struct kdtree
{
int ls,rs;
int mi[2],mx[2];
point p;
}tree[maxl];
typedef pair<int,int> p;
typedef pair<long long,p> pp;
priority_queue<pp,vector<pp>,greater<pp> > q;
set <p> ss;
inline long long dist(point a,point b)
{
long long ret=0;
for(int i=0;i<2;i++)
ret+=1ll*(a.x[i]-b.x[i])*(a.x[i]-b.x[i]);
return ret;
}
inline void push_up(int k)
{
int s=tree[k].ls;
if(s)
for(int i=0;i<2;i++)
tree[k].mx[i]=max(tree[k].mx[i],tree[s].mx[i]),
tree[k].mi[i]=min(tree[k].mi[i],tree[s].mi[i]);
s=tree[k].rs;
if(s)
for(int i=0;i<2;i++)
tree[k].mx[i]=max(tree[k].mx[i],tree[s].mx[i]),
tree[k].mi[i]=min(tree[k].mi[i],tree[s].mi[i]);
}
inline void build(int &k,int l,int r,int d)
{
idx=d;k=++tot;
tree[k].ls=tree[k].rs=0;
int mid=(l+r)>>1;
nth_element(a+l,a+mid,a+r+1);
tree[k].p=a[mid];
for(int i=0;i<2;i++)
tree[k].mi[i]=tree[k].mx[i]=a[mid].x[i];
if(l<mid)
build(tree[k].ls,l,mid-1,d^1);
if(mid<r)
build(tree[k].rs,mid+1,r,d^1);
push_up(k);
}
inline void prework()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i].x[0],&a[i].x[1]);
for(int j=0;j<2;j++)
b[i].x[j]=a[i].x[j];
a[i].val=b[i].val=i;
}
build(root,1,n,0);
}
inline long long calc(int k,point pt)
{
if(!k) return -1;
long long ret=0;
for(int i=0;i<2;i++)
ret+=pow(1ll*max(abs(tree[k].mi[i]-pt.x[i]),abs(tree[k].mx[i]-pt.x[i])),2);
return ret;
}
inline void qry(int k,point pt,int d)
{
if(!k) return;
idx=d;
pp nd;
nd=make_pair(dist(pt,tree[k].p),make_pair(tree[k].p.val,pt.val));
int flag=0;
if(tree[k].p.val!=pt.val)
{
if(q.size()<2*k)
q.push(nd),flag=1;
else
if(nd.first>q.top().first)
q.pop(),q.push(nd);
}
if(pt<tree[k].p)
{
if(q.size()<2*k || calc(tree[k].ls,pt)>q.top().first)
qry(tree[k].ls,pt,d^1);
if(q.size()<2*k || calc(tree[k].rs,pt)>q.top().first)
qry(tree[k].rs,pt,d^1);
}
else
{
if(q.size()<2*k || calc(tree[k].rs,pt)>q.top().first)
qry(tree[k].rs,pt,d^1);
if(q.size()<2*k || calc(tree[k].ls,pt)>q.top().first)
qry(tree[k].ls,pt,d^1);
}
}
inline void mainwork()
{
while(!q.empty()) q.pop();
for(int i=1;i<=n;i++)
qry(root,b[i],0);
p d;int x,y;
while(!q.empty())
{
x=q.top().second.first;y=q.top().second.second;
d=make_pair(min(x,y),max(x,y));
if(ss.find(d)==ss.end())
{
ss.insert(d);
ans[++ans[0]]=q.top().first;
}
q.pop();
}
}
inline void print()
{
printf("%lld",ans[ans[0]-k+1]);
}
int main()
{
prework();
mainwork();
print();
return 0;
}