bzoj4520【CQOI2016】K远点对

4520: [Cqoi2016]K远点对

Time Limit: 30 Sec   Memory Limit: 512 MB
Submit: 497   Solved: 241
[ Submit][ Status][ Discuss]

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



KD-Tree+优先队列优化搜索

本体要求无序的K远点对,实际就是有序的2K远点对。

用优先队列记录当前最大的2K个距离,然后在KD-Tree上搜索,用优先队列优化。




#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define sqr(x) (x)*(x)
#define ll long long
#define N 100005
#define inf 1000000000000000ll
using namespace std;
int n,k,Q,root,lc[N],rc[N];
ll mn[N][2],mx[N][2];
priority_queue<ll,vector<ll>,greater<ll> > q;
struct data
{
	ll d[2];
	friend bool operator <(data a,data b)
	{
		return a.d[Q]!=b.d[Q]?a.d[Q]<b.d[Q]:a.d[Q^1]<b.d[Q^1];
	}
}tmp,val[N];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline ll calc(data a,data b){return sqr(a.d[0]-b.d[0])+sqr(a.d[1]-b.d[1]);}
void pushup(int x)
{
	F(i,0,1)
	{
		mn[x][i]=mx[x][i]=val[x].d[i];
		mn[x][i]=min(mn[x][i],min(mn[lc[x]][i],mn[rc[x]][i]));
		mx[x][i]=max(mx[x][i],max(mx[lc[x]][i],mx[rc[x]][i]));
	}
}
int build(int l,int r,int k)
{
	if (l>r) return 0;
	int mid=(l+r)>>1;
	Q=k;
	nth_element(val+l,val+mid,val+r+1);
	lc[mid]=build(l,mid-1,k^1);
	rc[mid]=build(mid+1,r,k^1);
	pushup(mid);
	return mid;
}
ll get(int x)
{
	if (!x) return 0;
	ll ret=0;
	F(i,0,1) ret+=max(sqr(mx[x][i]-tmp.d[i]),sqr(mn[x][i]-tmp.d[i]));
	return ret;
}
void query(int x)
{
	if (!x) return;
	ll dl=get(lc[x]),dr=get(rc[x]),d=calc(tmp,val[x]);
	if (d>q.top()) q.pop(),q.push(d);
	if (dl>dr)
	{
		if (dl>q.top()) query(lc[x]);
		if (dr>q.top()) query(rc[x]);
	}
	else
	{
		if (dr>q.top()) query(rc[x]);
		if (dl>q.top()) query(lc[x]);
	}
}
int main()
{
	n=read();k=read();
	F(i,1,n) val[i].d[0]=read(),val[i].d[1]=read();
	F(i,0,1) mn[0][i]=inf,mx[0][i]=-inf;
	root=build(1,n,0);
	F(i,1,2*k) q.push(0);
	F(i,1,n) tmp=val[i],query(root);
	printf("%lld\n",q.top());
	return 0;
}


你可能感兴趣的:(优先队列,Kd-Tree)