平面最近点对分治105pts求助
查看原帖
平面最近点对分治105pts求助
188716
pokefunc楼主2023/2/8 18:19

rt,正常的 O(nlogn)\mathrm{O}(n \log n) 分治,错的都是WA

#include<cstdio>
#include<algorithm>
#include<cmath>
#define sqrrt(x) ceil(sqrt(x))
#define int long long
const int M=5e5+5;
const int INF=4e18;
inline int read(){int x(0),op(0);char ch=getchar();while(ch<'0'||ch>'9')op|=(ch==45),ch=getchar();while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();return op?-x:x;}
inline int ssread(){int x;scanf("%lld",&x);return x;}
#ifndef ONLINE_JUDGE
#define read ssread
#endif
struct point{int x,y;}p[M],q[M],t1[M],t2[M];
int n;
bool cmp1(point x,point y){return x.x!=y.x?x.x<y.x:x.y<y.y;}
bool cmp2(point x,point y){return x.y<y.y;}
int dist(point x,point y){return (x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y);}
int solve(int l,int r){
	if(l==r)return INF;
	int mid=l+r>>1;
	int ans=std::min(solve(l,mid),solve(mid+1,r)),pp=p[mid].x; 
	for(int k=l,i=l,j=mid+1;k<=r;++k){
		if(j>r||(i<=mid&&p[i].y<p[j].y))q[k]=p[i++];
		else q[k]=p[j++];
	}
	for(int i=l;i<=r;++i)p[i]=q[i];
	int p1=0,p2=0;
	for(int i=l;i<=r;++i){
		if(p[i].x<=pp&&pp-p[i].x<=sqrrt(ans))t1[++p1]=p[i];
		if(p[i].x>pp&&p[i].x-pp<=sqrrt(ans))t2[++p2]=p[i];
	}
	for(int k=1,i=1,j=1;k<=p1;++k){
		while(i<=p2&&t2[i].y<=t1[k].y-sqrrt(ans))i++;
		while(j<=p2&&t2[j].y<t1[k].y+sqrrt(ans))j++;
		for(int tmp=i;tmp<j;++tmp)ans=std::min(ans,dist(t1[k],t2[tmp]));
	}
	return ans;
}
signed main(){
	n=read();
	for(int i=1;i<=n;++i){
		int x=read(),y=read();
		p[i]=(point){x,y};
	}
	std::sort(p+1,p+n+1,cmp1);
	printf("%lld\n",solve(1,n));
	return 0;
}
2023/2/8 18:19
加载中...