分析
我们可以枚举每一个点算它的最近点
估价函数应该分为3种情况计算:
大于max,小于min,位于min和max之间
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
#define int long long
const int inf = 1e18;
struct kd {
int d[2],mx[2],mn[2],le,ri,id;
};
kd t[300100],now;
int n,m,root,wh,Ans=inf,sum,x[300100],y[300100];
inline bool operator < (kd a,kd b){
return a.d[wh]<b.d[wh];
}
inline void up(int rt){
for(int i=0;i<2;i++){
t[rt].mn[i]=min(t[rt].mn[i],min(t[t[rt].le].mn[i],t[t[rt].ri].mn[i]));
t[rt].mx[i]=max(t[rt].mx[i],max(t[t[rt].le].mx[i],t[t[rt].ri].mx[i]));
}
}
inline void build(int &x,int le,int ri,int wwh){
wh=wwh;
int mid=(le+ri)>>1;
x=mid;
nth_element(t+le,t+x,t+ri+1);
for(int i=0;i<2;i++)
t[x].mn[i]=t[x].mx[i]=t[x].d[i];
if(le<x)build(t[x].le,le,mid-1,wwh^1);
if(ri>x)build(t[x].ri,mid+1,ri,wwh^1);
up(x);
}
inline int getd(kd a,kd b){
return (a.d[0]-b.d[0])*(a.d[0]-b.d[0])+(a.d[1]-b.d[1])*(a.d[1]-b.d[1]);
}
inline int calc(int x){
if(!x)return inf;
int res=0;
for(int i=0;i<2;i++){
if(now.d[i]<t[x].mn[i])res+=(now.d[i]-t[x].mn[i])*(now.d[i]-t[x].mn[i]);
else if(now.d[i]>t[x].mx[i])res+=(now.d[i]-t[x].mx[i])*(now.d[i]-t[x].mx[i]);
}
return res;
}
inline void qurey(int x){
if(!x)return;
int dl=calc(t[x].le),dr=calc(t[x].ri),d=getd(t[x],now);
if(d!=0&&d<Ans)Ans=d;
if(d==0)sum++;
if(dl<dr){
if(dl<Ans)qurey(t[x].le);
if(dr<Ans)qurey(t[x].ri);
}else {
if(dr<Ans)qurey(t[x].ri);
if(dl<Ans)qurey(t[x].le);
}
}
signed main(){
int i,j,k;
t[0].mn[0]=t[0].mn[1]=inf;
t[0].mx[0]=t[0].mx[1]=-inf;
scanf("%lld",&n);
for(i=1;i<=n;i++){
scanf("%lld%lld",&x[i],&y[i]);
t[i].d[0]=x[i],t[i].d[1]=y[i];
t[i].id=i;
}
build(root,1,n,1);
for(i=1;i<=n;i++){
sum=0;
now.d[0]=x[i],now.d[1]=y[i];
qurey(root);
if(sum>1){
Ans=0;
break;
}
}
double out=sqrt((double)Ans);
printf("%0.4lf
",out);
return 0;
}