【题目描述】
Description
已知平面内 N 个点的坐标,求欧氏距离下的第 K 远点对。
Input
输入文件第一行为用空格隔开的两个整数 N, K。接下来 N 行,每行两个整数 X,Y,表示一个点
的坐标。1 < = N < = 100000, 1 < = K < = 100, K < = N*(N−1)/2 , 0 < = X, Y < 2^31。
Output
输出文件第一行为一个整数,表示第 K 远点对的距离的平方(一定是个整数)。
Sample Input
10 5
0 0
0 1
1 0
1 1
2 0
2 1
1 2
0 2
3 0
3 1
0 0
0 1
1 0
1 1
2 0
2 1
1 2
0 2
3 0
3 1
Sample Output
9
HINT
Source
【题解】 KD-tree裸题
用小根堆维护当前答案,query判断范围时与堆顶元素比较
/* -------------- user Vanisher problem bzoj-4520 ----------------*/ # include <bits/stdc++.h> # define ll long long # define inf 6e9 # define N 100010 using namespace std; priority_queue <ll,vector<ll>,greater<ll> > hp; ll read(){ ll tmp=0, fh=1; char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();} while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();} return tmp*fh; } struct point{ ll x,y; }p[N]; struct node{ ll lx,ly,rx,ry,pl,pr,tag; point num; }T[N]; ll place,n,k; double sqr(double x){return x*x;} void change(ll now){ T[now].lx=min(T[now].num.x,min(T[T[now].pl].lx,T[T[now].pr].lx)); T[now].rx=max(T[now].num.x,max(T[T[now].pl].rx,T[T[now].pr].rx)); T[now].ly=min(T[now].num.y,min(T[T[now].pl].ly,T[T[now].pr].ly)); T[now].ry=max(T[now].num.y,max(T[T[now].pl].ry,T[T[now].pr].ry)); } bool cmpx(point x, point y){return x.x<y.x;} bool cmpy(point x, point y){return x.y<y.y;} ll build(ll l, ll r){ if (l>r) return 0; ll now=++place,mid=(l+r)/2; double sumx=0,sumy=0,deltax=0,deltay=0; for (ll i=l; i<=r; i++) sumx=sumx+p[i].x, sumy=sumy+p[i].y; sumx=sumx/(r-l+1); sumy=sumy/(r-l+1); for (ll i=l; i<=r; i++){ deltax=deltax+sqr(p[i].x-sumx); deltay=deltay+sqr(p[i].y-sumy); } if (deltax>deltay){ T[now].tag=0; nth_element(p+l,p+mid,p+r+1,cmpx); } else{ T[now].tag=1; nth_element(p+l,p+mid,p+r+1,cmpy); } T[now].num=p[mid]; T[now].pl=build(l,mid-1); T[now].pr=build(mid+1,r); change(now); return now; } ll distmx(ll now, point x){ ll num=sqr(max(abs(T[now].lx-x.x),abs(T[now].rx-x.x))); num=num+sqr(max(abs(T[now].ly-x.y),abs(T[now].ry-x.y))); return num; } void solve(ll now, point x){ if (now==0) return; ll d0=sqr(T[now].num.x-x.x)+sqr(T[now].num.y-x.y),d1,d2; if (d0>hp.top()){ hp.pop(); hp.push(d0); } if (T[now].pl!=0) d1=distmx(T[now].pl,x); else d1=-1; if (T[now].pr!=0) d2=distmx(T[now].pr,x); else d2=-1; if (d1>d2){ if (d1>hp.top()) solve(T[now].pl,x); if (d2>hp.top()) solve(T[now].pr,x); } else { if (d2>hp.top()) solve(T[now].pr,x); if (d1>hp.top()) solve(T[now].pl,x); } } int main(){ n=read(); k=read(); T[0].ly=T[0].lx=inf; T[0].rx=T[0].ry=-inf; for (ll i=1; i<=2*k; i++) hp.push(-1); for (ll i=1; i<=n; i++) p[i].x=read(), p[i].y=read(); ll rt=build(1,n); for (ll i=1; i<=n; i++) solve(rt,p[i]); printf("%lld ",hp.top()); return 0; }