一直想学怎么求平面最近点对,看了一上午oi wiki整明白了
传送门 https://oi-wiki.org/geometry/nearest-points/
大致思路
1.开始分治前将所有点按x坐标排序
2.分治(l,r),如果r-l<=5,那么直接暴力求出结果然后返回
3.反之分治左右区间,设左右子区间求出的答案为ans,
合并时取出(l,r)的中点mid, 把所有x坐标在[xmid-ans,xmid+ans]范围的点加入集合B
将集合B中点按照y坐标排序
按y坐标从小到大枚举B中点i,找出B中所有y坐标在[yi,yi+ans]范围内的点j,用点i,点j更新答案(想想这么暴力为什么不会超过O(nlogn)复杂度?)
db closepoint(vector<point>&A,int l,int r){ // 最近点对 , 先要按照 x 坐标排序 if (r-l<=5){ db ans=1e20; for (int i=l;i<=r;i++) for (int j=i+1;j<=r;j++) ans=min(ans,A[i].dis(A[j])); return ans; } int mid=l+r>>1; db ans=min(closepoint(A,l,mid),closepoint(A,mid+1,r)); vector<point>B; for (int i=l;i<=r;i++) if (abs(A[i].x-A[mid].x)<=ans) B.push_back(A[i]); sort(B.begin(),B.end(),[](point k1,point k2){return k1.y<k2.y;}); for (int i=0;i<B.size();i++) for (int j=i+1;j<B.size()&&B[j].y-B[i].y<ans;j++) ans=min(ans,B[i].dis(B[j])); return ans; }