已知平面内 N 个点的坐标,求欧氏距离下的第 K 远点对。
已知平面内 N 个点的坐标,求欧氏距离下的第 K 远点对。
输出文件第一行为一个整数,表示第 K 远点对的距离的平方(一定是个整数)。
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; }