袭击
这道题目的解法是在计算距离时,如果是同一类点就认为距离时无穷大
但是这样的话就会存在一个问题,如果我们递归到某一层的时候,得到的最小距离还是无穷大,那么此时我们再执行原来的算法,时间复杂度就会变成
即使我们使用一般的算法(就是普通的平面最近点对),然后把
for(int i=1;i<cnt;i++)
for(int j=i+1;j<=cnt&&(temp[j].y-temp[i].y)*(temp[j].y-temp[i].y)<d;j++)//最多只有6个点
d=min(d,dis(temp[i],temp[j]));
改成
for(int i=1;i<cnt;i++)
for(int j=i+1;j<=cnt&&temp[j].y-temp[i].y<d;j++)
if(temp[i].id^temp[j].id==1) d=min(d,dis(temp[i],temp[j]));
也不行
首先一种hack数据就是同一个地方可能有多个重合的点,此时我们有一个很好的解决方法,对同一类型的点,在相同位置的只保留一个就行了,这里用hash即可
另一种hack数据就是最开始提到的情况,比如这道题目的最后一个数据,所有点都分布在
确定性的大致代码见下
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e5+10;
map<pair<ll,ll>,bool> h;
int n;
struct Node
{
ll x,y;
int id;
}temp[N],w[N],s1[N],s2[N];
int read()
{
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-f;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-48;s=getchar();}
return x*f;
}
bool cmp(Node i,Node j)
{
if(i.x==j.x) return i.y<j.y;
return i.x<j.x;
}
double dis(Node i,Node j)
{
return sqrt((i.x-j.x)*(i.x-j.x)+(i.y-j.y)*(i.y-j.y));
}
double cal(int l,int r)
{
if(l==r) return 10000000000;
bool flag=0;
for(int i=l+1;i<=r;i++)
if(w[i].id!=w[l].id)
{
flag=1;
break;
}
if(!flag) return 10000000000;
int mid=l+r>>1,cnt=0,tot=0;
double d1=cal(l,mid),d2=cal(mid+1,r);
if(d1==10000000000&&d2==10000000000)
{
}
double d=min(d1,d2);
int i=l,j=mid+1;
while(i<=mid||j<=r)
{
while(i<=mid&&abs(w[i].x-w[mid].x)>=d)//先筛选出在虚线框中的点
i++;
while(j<=r&&abs(w[j].x-w[mid].x)>=d)
j++;
if(i<=mid)
{
if(j<=r)
{
if(w[i].y<w[j].y) temp[++cnt]=w[i++];//仍然按照y坐标升序
else temp[++cnt]=w[j++];
}
else temp[++cnt]=w[i++];
}
else if(j<=r) temp[++cnt]=w[j++];
}
for(int i=1;i<cnt;i++)
for(int j=i+1;j<=cnt&&temp[j].y-temp[i].y<d;j++)
if(temp[i].id^temp[j].id==1) d=min(d,dis(temp[i],temp[j]));
i=l,j=mid+1;
int k=l;
while(i<=mid&&j<=r)//归并排序
{
if(w[i].y<w[j].y) temp[k++]=w[i++];
else temp[k++]=w[j++];
}
while(i<=mid) temp[k++]=w[i++];
while(j<=r) temp[k++]=w[j++];
for(int i=l;i<=r;i++)
w[i]=temp[i];
return d;
}
int main()
{
int t=read();
while(t--)
{
n=read();
int cnt=0;
for(int i=1;i<=n;i++)
{
ll x=read(),y=read();
if(h.find(make_pair(x,y))!=h.end()) continue;
h[make_pair(x,y)]=1;
w[++cnt].x=x,w[cnt].y=y,w[cnt].id=0;
}
h.clear();
for(int i=1;i<=n;i++)
{
ll x=read(),y=read();
if(h.find(make_pair(x,y))!=h.end()) continue;
h[make_pair(x,y)]=1;
w[++cnt].x=x,w[cnt].y=y,w[cnt].id=1;
}
sort(w+1,w+cnt+1,cmp);
printf("%.3lf\n",cal(1,cnt));
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构