分治卡常,有注释,玄关
查看原帖
分治卡常,有注释,玄关
774854
qzmoot楼主2024/5/3 15:39

RTRT

#include <bits/stdc++.h>
using namespace std;
typedef long long ll; 
const ll N=4e5+5,inf=1ll<<62;
ll n,ans=inf;
struct node{
	ll x,y;
}a[N];//结构体 
ll read()
{
	ll x=0,f=1;
	char ch=getchar();
	while(!isdigit(ch))
	{
		if(ch=='-')
			f=-1;
		ch=getchar();
	}
	while(isdigit(ch))
	{
		x=x*10+ch-'0';
		ch=getchar();
	}
	return x*f;
}//快读 
bool cmpx(node u,node v)
{
	return u.x<v.x;
}
bool cmpy(node u,node v)
{
	return u.y<v.y;
}//快排比较 
ll dis(node u,node v)
{
	return (u.x-v.x)*(u.x-v.x)+(u.y-v.y)*(u.y-v.y);
}//算距离 
void fz(ll l,ll r)//这里我采用的是[l,(l+r)/2],[(l+r)/2+1,r]的分治 
{
	if(l>=r)//只有一个点 
		return;
	if(l+1==r)//有两个点 
	{
		ans=min(ans,dis(a[l],a[r])); 
		return;
	}
	ll mid=l+r>>1;//算中间值 
	fz(l,mid);
	fz(mid+1,r);//向下分治 
	vector<node>gd;//存储可以更新的点 
	ll gx=a[mid].x;//中间值 
	for(ll i=l;i<=r;++i)
		if(abs(gx-a[i].x)<sqrt(ans))//如果比之前答案小 
			gd.push_back(a[i]);
	sort(gd.begin(),gd.end(),cmpy);//按纵坐标排序 
	for(vector<node>::iterator L=gd.begin(),R=L;L!=gd.end();++L)//双指针 
	{
		while(R!=gd.end() && R->y<=L->y+ans)
			++R;//右指针更新 
		for(vector<node>::iterator m=L+1;m!=R;++m)
			ans=min(ans,dis(*L,*m));//计算 
	}
}
int main()
{
	n=read();
	for(ll i=1;i<=n;++i)
		a[i].x=read(),a[i].y=read();//输入 
	sort(a+1,a+1+n,cmpx);//排序 
	fz(1,n);//分治 
	printf("%lld",ans);//输出 
	return 0; 
}
2024/5/3 15:39
加载中...