Luogu 1429(平面最近点对)(模板)

传送门

O(nlogn)算法详解参考此博客

时间复杂度证明参考此博客

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=2e5+4;
const double INF=1e100;
int n;
struct Point {
	double x,y;
	friend bool operator <(const Point &a,const Point &b) {
		return a.x<b.x;
	}
}p[N],t[N];
inline double dis(Point a,Point b) {
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline void smin(double &x,double y) {
	x=x>y?y:x;
}
inline double Abs(double x) {
	return x>0?x:-x;
}
inline void Swap(Point *a,Point *b) {
	Point t;
	t=*a,*a=*b,*b=t;
}
inline double divide(int l,int r) {
	if (l==r) return INF;
	int mid=l+r>>1;
	double tx=p[mid].x;//save p[mid].x since mid would change later!
	double ret=min(divide(l,mid),divide(mid+1,r));
	int p1=l,p2=mid+1;
	int tot=0;
	while (p1<=mid||p2<=r) {
		if (p2<=r&&(p[p1].y>p[p2].y||p1>mid)) t[tot++]=p[p2++];
		else t[tot++]=p[p1++];//(p2>r||(p[p1].y<=p[p2].y&&p1<=mid))
	}
	for (int i=0;i<tot;++i) p[l+i]=t[i];
	for (int i=1;i<tot;++i) {
		if (Abs(t[i].x-tx)>=ret) continue;
		for (int j=i-1;~j&&t[i].y-t[j].y<ret;--j)
			smin(ret,dis(t[i],t[j]));
	}
	return ret;
}
int main() {
//	freopen("in2.txt","r",stdin);
	scanf("%d",&n);
	for (register int i=1;i<=n;++i)	scanf("%lf%lf",&p[i].x,&p[i].y);
	sort(p+1,p+n+1);
	printf("%.4lf\n",divide(1,n));
	return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值