一道分治的经典题,我用的是分治。
第8个点WA了,并且误差大的离谱。
求调
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int n;
struct node{double x,y;int id;};
node a[200005];
node b[200005];
int bin[200005];
int inb[200005];
int bn[200005];
int lin[200005];
int rin[200005];
inline void in(double &n){
n=0;
char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0'&&c<='9') n=n*10+c-'0',c=getchar();
if(c!='.') return ;
double x=1;
c=getchar();
while(c>='0'&&c<='9') n+=0.1*x*(c-'0'),c=getchar(),x*=0.1;
return ;
}
bool cmp(node p,node q){return p.x==q.x?p.y<q.y:p.x<q.x;}
bool cmp2(node p,node q){return p.y==q.y?p.x<q.x:p.y<q.y;}
inline double dis(int i,int j){return sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));}
double solve(int l,int r){
if(l+1==r) return dis(l,r);
if(l+2==r) return min(min(dis(l,l+1),dis(l,r)),dis(l+1,r));
int mid=l+r>>1;
double dd=min(solve(l,mid),solve(mid+1,r)),md=a[mid].x;
int ls=0,rs=0;
for(int i=l;i<=mid;i++)
if(md-a[i].x<=dd) lin[++ls]=bn[i];
for(int i=mid+1;i<=r;i++)
if(a[i].x-md<=dd) rin[++rs]=bn[i];
if(ls==0||rs==0) return dd;
int rt=1;
double ddd=2e9;
for(int i=1;i<=ls;i++){
while(b[rin[rt]].y<=b[lin[i]].y&&b[lin[i]].y-b[rin[rt]].y>dd&&rt<rs) rt++;
for(int j=rt;j<=min(rt+10,rs);j++)
ddd=min(ddd,sqrt((b[lin[i]].x-b[rin[j]].x)*((b[lin[i]].x-b[rin[j]].x))+(b[lin[i]].y-b[rin[j]].y)*(b[lin[i]].y-b[rin[j]].y)));
}
return min(dd,ddd);
}
int main(){
// freopen("qwq.in","r",stdin);
scanf("%d",&n);
for(int i=1;i<=n;i++) in(a[i].x),in(a[i].y),a[i].id=i,b[i]=a[i];
// for(int i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y),a[i].id=i,b[i]=a[i];
sort(a+1,a+1+n,cmp);
for(int i=2;i<=n;i++)
if(a[i].x==a[i-1].x&&a[i].y==a[i-1].y){
printf("0.0000");
return 0;
}
sort(b+1,b+1+n,cmp2);
for(int i=1;i<=n;i++) bin[a[i].id]=i,inb[b[i].id]=i;
for(int i=1;i<=n;i++) bn[bin[i]]=inb[i];
printf("%.4lf",solve(1,n));
return 0;
}