题目描述
给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的
输入输出格式
输入格式:
第一行:n;2≤n≤200000
接下来n行:每行两个实数:x y,表示一个点的行坐标和列坐标,中间用一个空格隔开。
输出格式:
仅一行,一个实数,表示最短距离,精确到小数点后面4位。
输入输出样例
输入样例#1:
复制
3 1 1 1 2 2 2
输出样例#1: 复制
1.0000
说明
0<=x,y<=10^9
题解
考场清晰的记得以前听过,并且记错做法还觉得自己是天才......
考场思路:按横轴排序,然后从左往右枚举每个点,把和该点的横坐标之差小于$ans$的点暴力算。
然后怕构造数据被卡(很多个点的横坐标差不多,竖轴差很多的话可以卡成$N$方),于是考虑用权值线段树优化竖轴,也就是从权值线段树中取竖轴在当前点加减ans范围的点暴力算。(考试$x,y$范围1e6)
这样应该就不会T了......
然后毒瘤评测人只给64M啊!哪里够开权值线段树啊!
于是把扫描线转了45°(也可以理解为把纸转45°),再做类暴力,这样就不好卡了。
然后就过了2333
1 /* 2 qwerta 3 P1429 平面最近点对(加强版) 4 Accepted 5 100 6 代码 C++,1.16KB 7 提交时间 2018-10-19 15:55:35 8 耗时/内存 9 348ms, 2064KB 10 */ 11 #include<algorithm> 12 #include<iostream> 13 #include<cstdio> 14 #include<cmath> 15 using namespace std; 16 #define R register 17 inline int read() 18 { 19 char ch=getchar(); 20 int x=0; 21 while(!isdigit(ch))ch=getchar(); 22 while(isdigit(ch)){x=x*10+ch-‘0‘;ch=getchar();} 23 return x; 24 } 25 const int MAXN=200000+3,MAXX=1000000+3; 26 struct emm{ 27 int x,y; 28 }a[MAXN]; 29 const double k=-0.5; 30 bool cmp(emm qaq,emm qwq) 31 { 32 return qaq.y-k*qaq.x<qwq.y-k*qwq.x; 33 } 34 inline double dis(int u,int v) 35 { 36 return sqrt(1LL*(a[u].x-a[v].x)*(a[u].x-a[v].x)+1LL*(a[u].y-a[v].y)*(a[u].y-a[v].y)); 37 } 38 double gen2=sqrt(2); 39 inline double je(int u,int v) 40 { 41 return abs(((a[u].y-k*a[u].x)-(a[v].y-k*a[v].x)))/gen2; 42 } 43 int main() 44 { 45 //freopen("dark.in","r",stdin); 46 //freopen("dark.out","w",stdout); 47 int n=read(); 48 for(R int i=1;i<=n;++i) 49 a[i].x=read(),a[i].y=read(); 50 sort(a+1,a+n+1,cmp); 51 int l=1,r=1; 52 double ans=dis(1,2); 53 for(R int u=1;u<=n;++u) 54 { 55 while(je(u,l)>ans)++l; 56 while(je(r+1,u)<ans&&r<n)++r; 57 //cout<<u<<" "<<l<<" "<<r<<endl; 58 for(R int v=l;v<=r;++v) 59 if(u!=v) 60 ans=min(ans,dis(u,v)); 61 } 62 printf("%.4f",ans); 63 return 0; 64 }
原文地址:https://www.cnblogs.com/qwerta/p/9819241.html
时间: 2024-11-07 20:17:21