码迷,mamicode.com
首页 > 其他好文 > 详细

平面最近点对问题

时间:2020-03-03 12:37:54      阅读:75      评论:0      收藏:0      [点我收藏+]

标签:ret   printf   通过   string   scanf   else   line   code   ring   

平面上\(n\)个点,求距离最近的两个点的距离。

通过分治求解。把所有点按\(x\)排序,每次从最中间的那个点分开(设其横坐标为\(M\)),递归求解左右两区域的最近点对,再求跨过中线的最近点对。

设递归左右区域后,当前答案为\(d\),显然:
1.如果想让\(d\)变小,就要找到距离\(\leq d\)的点对,所以只用考虑横坐标与中线相差不超过\(d\)的点。
2.左右两区域内的点,两两距离\(\geq d\)

枚举左区域中的点\((a,b)\),需要考虑的右边的点只有横坐标不超过\(M+d\),纵坐标在\([b-d,b+d]\)内的点。考虑在一个\(d*2d\)的矩形内塞尽量多的点,使得两两距离\(\geq d\),这样的点最多有六个,所以整个算法的时间复杂度\(O(n\log n)\)

CF429D

一个长度为\(n\)的序列\(a\),定义\(f(l,r)=(r-l)^2+(\sum_{i=l+1}^r a_i)^2\),求\(f(l,r)\)的最小值。

明显就是\(n\)个点\((i,s_i)\)求个最近点对。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define mid ((l+r)>>1)
using namespace std;
typedef long long LL;
const int mxn=100010;
struct nd{
    int x,y;
    bool operator<(const nd a)const{
        return y<a.y;
    }
}a[mxn],b[mxn];
int n;
LL ans;
LL dis(nd x,nd y){
    return 1ll*(x.x-y.x)*(x.x-y.x)+1ll*(x.y-y.y)*(x.y-y.y);
}
void solve(int l,int r){
    if (l==r) return;
    int M=a[mid].x;
    solve(l,mid),solve(mid+1,r);
    int d=sqrt(ans),cur=1,m=0;
    for (int i=mid+1;i<=r;++i)
        if (a[i].x<=M+d) b[++m]=a[i];
    for (int i=l;i<=mid;++i)
        if (a[i].x>=M-d){
            for (;cur<=m&&b[cur].y<a[i].y-d;++cur);
            for (int j=cur;j<=m&&b[j].y<=a[i].y+d;++j) ans=min(ans,dis(a[i],b[j]));
        }
    int pa=l,pb=mid+1,p=l;
    for (;pa<=mid&&pb<=r;)
        if (a[pa]<a[pb]) b[p++]=a[pa++];
        else b[p++]=a[pb++];
    for (;pa<=mid;b[p++]=a[pa++]);
    for (;pb<=r;b[p++]=a[pb++]);
    for (int i=l;i<=r;++i) a[i]=b[i];
}
int main()
{
    scanf("%d",&n);
    for (int i=1,x,s=0;i<=n;++i)
        scanf("%d",&x),a[i]=(nd){i,s+=x};
    ans=1e18;
    solve(1,n);
    printf("%lld\n",ans);
    return 0;
}

平面最近点对问题

标签:ret   printf   通过   string   scanf   else   line   code   ring   

原文地址:https://www.cnblogs.com/zzqtxdy/p/12401553.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!