[bzoj][Cqoi2016]K远点对【堆】【KD-tree】

【题目描述】

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

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;
}


原文地址:https://www.cnblogs.com/Vanisher/p/9136045.html