题目描述
给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的
输入输出格式
输入格式:
第一行:n;2≤n≤200000
接下来n行:每行两个实数:x y,表示一个点的行坐标和列坐标,中间用一个空格隔开。
输出格式:
仅一行,一个实数,表示最短距离,精确到小数点后面4位。
输入输出样例
说明
0<=x,y<=10^9
题目链接:https://www.luogu.org/problem/show?pid=1429
解题报告:
分治经典题,复杂度O(nlogn).
AC代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define FOR(i,s,t) for(register int i=s;i<=t;++i)
#define db double
#define BIG 400011
#define ll long long
class point{
public:
db x=0,y=0;
inline bool operator<(point A)const{
return x<A.x||(x==A.x)&&(y<A.y);
}
inline db operator-(point A)const{
return (db)(sqrt((db)(x-A.x)*(x-A.x)+(db)(y-A.y)*(y-A.y)));
}
private:
}p[BIG],b[BIG];
inline db Qmin(db a,db b){
return a<b?a:b;
}
db ans=1000000000.00;
inline void merge(int l,int r){
if(l==r)return;
int mid=l+r>>1,t=0,pos=1;
merge(l,mid);merge(mid+1,r);
db line=p[mid].x;
FOR(i,l,mid)if(line-p[i].x<ans)b[++t]=p[i];
FOR(i,mid+1,r){
if(p[i].x-line>=ans)continue;
while(p[i].x-b[pos].x>=ans&&pos<=t)++pos;
for(register int j=pos;j<=t&&p[i].x-b[j].x<ans;++j)ans=Qmin(p[i]-b[j],ans);
}
}
int n;
int main(){
scanf("%d",&n);
FOR(i,1,n)
scanf("%lf%lf",&p[i].x,&p[i].y);
sort(p+1,p+n+1);
merge(1,n);
printf("%.4lf\n",ans);
return 0;
}