KD-Tree暴力大法吼哇!
容易发现如果我们给每个点求出\(K\)个最远距离,放在一起找出其中的第\(2K\)大的就是答案(一对点会算两次)
考虑搞出一个小根堆,刚开始往里面放\(2K\)个\(0\)。然后我们枚举每个点,不断地找出距离它的最远点然后和堆顶比较,如果大于就替换掉堆顶
最后答案就是堆顶,而这种做法正确性显然且有一定剪枝,但复杂度是\(O(n^2)\)级别的
然后我们就KD-Tree来实现暴力的过程即可(滑稽),复杂度\(O(\text{玄学})\),实测最慢跑了70ms。。。
#include
#include
#include
#include
#define RI register int
#define CI const int&
using namespace std;
typedef long long LL;
const int N=100005; const LL INF=1e18;
int D; priority_queue < LL,vector ,greater > hp;
struct point
{
int d[2];
friend inline bool operator < (const point& A,const point& B)
{
return A.d[D]==B.d[D]?A.d[D^1]>1; D=d; nth_element(a+l+1,a+mid+1,a+r+1);
P(now)=Mi(now)=Mx(now)=a[mid];
if (l!=mid) build(lc(now),l,mid-1,d^1),pushup(now,lc(now));
if (r!=mid) build(rc(now),mid+1,r,d^1),pushup(now,rc(now));
}
inline void querymax(CI now)
{
if (!now) return; if (getmax(now)hp.top()) hp.pop(),hp.push(tp);
LL ml=getmax(lc(now)),mr=getmax(rc(now));
if (ml>mr) querymax(lc(now)),querymax(rc(now));
else querymax(rc(now)),querymax(lc(now));
}
#undef lc
#undef rc
#undef P
#undef Mi
#undef Mx
}KD;
int main()
{
RI i; for (scanf("%d%d",&n,&k),i=1;i<=n;++i) scanf("%d%d",&a[i].d[0],&a[i].d[1]);
for (KD.build(rt),i=1;i<=2*k;++i) hp.push(0); for (i=1;i<=n;++i)
s=(point){a[i].d[0],a[i].d[1]},KD.querymax(rt); return printf("%lld",hp.top()),0;
}