题意

给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的

2≤n≤200000

分析

参照3A17K的题解。

我们充分发扬人类智慧:

将所有点全部绕原点旋转同一个角度,然后按xx坐标排序

根据数学直觉,在随机旋转后,答案中的两个点在数组中肯定不会离得太远

所以我们只取每个点向后的5个点来计算答案

这样速度快得飞起,在n=1000000时都可以在1s内卡过


……

代码

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=2e5+50;
#define D double
struct spot{
    D a[4];
}p[N];
D x,y,x_,y_,z,w,ans;
int n;
bool mmp(const spot &u,const spot &v){
    return u.a[0]<v.a[0];
}
int main(){
    scanf("%d",&n);
    z=sin(1),w=cos(1);  //旋转1弧度≈57°
    for(int i=1;i<=n;i++){
        scanf("%lf%lf",&x,&y);
        x_=x*w-y*z;
        y_=x*z+y*w;   //计算旋转后的坐标
        p[i].a[0]=x_;
        p[i].a[1]=y_;
        p[i].a[2]=x;
        p[i].a[3]=y;   //存下来
    }
    sort(p+1,p+n+1,mmp);   //排序
    for(int i=n+1;i<=n+10;i++)
    p[i].a[0]=p[i].a[1]=-N-0.01;  //边界处理
    ans=2e9+0.01;  //初始化答案
    for(int i=1;i<=n;i++)
    for(int j=1;j<=5;j++){  //枚举
        x=p[i].a[2];y=p[i].a[3];
        x_=p[i+j].a[2];y_=p[i+j].a[3];
        z=sqrt((x-x_)*(x-x_)+(y-y_)*(y-y_));  //计算距离
        if(ans>z)ans=z;   //更新答案
    }
    printf("%.4lf\n",ans);  //输出
}
/*
x'=xcosθ-ysinθ
y'=xsinθ+ycosθ
*/

正常向的代码

#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
    rg T data=0,w=1;
    rg char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        data=data*10+ch-'0',ch=getchar();
    return data*w;
}
template<class T>il T read(rg T&x){
    return x=read<T>();
}
typedef long long ll;
using namespace std;
co double INF=1e18;

co int N=2e5+1;
struct node{
    double x,y;
}a[N],b[N];
bool cx(co node&a,co node&b){
    return a.x<b.x;
}
bool cy(co node&a,co node&b){
    return a.y<b.y;
}
double dis(co node&a,co node&b){
    return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2));
}
double merge(int l,int r){
    if(l==r) return INF;
    int mid=(l+r)>>1,cnt=0;
    double ans=min(merge(l,mid),merge(mid+1,r));
    for(int i=l;i<=r;++i) if(abs(a[i].x-a[mid].x)<=ans)
        b[++cnt]=a[i];
    sort(b+1,b+cnt+1,cy);
    for(int i=1;i<=cnt;++i)
        for(int j=i+1;j<=cnt;++j){
            if(b[j].y-b[i].y>ans) break;
            ans=min(ans,dis(b[i],b[j]));
        }
    return ans;
}
int main(){
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    int n=read<int>();
    for(int i=1;i<=n;++i)
        read(a[i].x),read(a[i].y);
    sort(a+1,a+n+1,cx);
    printf("%.4lf",merge(1,n));
    return 0;
}

LG1429 平面最近点对(加强版)的更多相关文章

  1. P1429 平面最近点对[加强版] 随机化

    LINK:平面最近点对 加强版 有一种分治的做法 因为按照x排序分治再按y排序 可以证明每次一个只会和周边的六个点进行更新. 好像不算很难 这里给出一种随机化的做法. 前置知识是旋转坐标系 即以某个点 ...

  2. 「LuoguP1429」 平面最近点对(加强版)

    题目描述 给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的 输入输出格式 输入格式: 第一行:n:2≤n≤200000 接下来n行:每行两个实数:x y, ...

  3. Luogu P1429 平面最近点对(加强版)(分治)

    P1429 平面最近点对(加强版) 题意 题目描述 给定平面上\(n\)个点,找出其中的一对点的距离,使得在这\(n\)个点的所有点对中,该距离为所有点对中最小的. 输入输出格式 输入格式: 第一行: ...

  4. P1429 平面最近点对(加强版)(分治)

    P1429 平面最近点对(加强版) 主要思路: 分治,将点按横坐标为第1关键字升序排列,纵坐标为第2关键字升序排列,进入左半边和右半边进行分治. 设d为左右半边的最小点对值.然后以mid这个点为中心, ...

  5. [Luogu1429]平面最近点对(加强版)

    题目大意: 平面最近点对. 思路: 分治. 首先将所有点排序 每次把当前区间分为两半,递归求解两个区间内部的情况,然后枚举区间两边的点. #include<cmath> #include& ...

  6. 计算几何 平面最近点对 nlogn分治算法 求平面中距离最近的两点

    平面最近点对,即平面中距离最近的两点 分治算法: int SOLVE(int left,int right)//求解点集中区间[left,right]中的最近点对 { double ans; //an ...

  7. HDU-4631 Sad Love Story 平面最近点对

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4631 数据是随机的,没有极端数据,所以可以分段考虑,最小值是一个单调不增的函数,然后每次分治算平面最近 ...

  8. HDU1007--Quoit Design(平面最近点对)

    Problem Description Have you ever played quoit in a playground? Quoit is a game in which flat rings ...

  9. Vijos 1012 清帝之惑之雍正 平面最近点对(分治)

    背景 雍正帝胤祯,生于康熙十七年(1678)是康熙的第四子.康熙61年,45岁的胤祯继承帝位,在位13年,死于圆明园.庙号世宗. 胤祯是在康乾盛世前期--康熙末年社会出现停滞的形式下登上历史舞台的.复 ...

随机推荐

  1. centos下搭建DNS

    一.DNS名词介绍: ( Domain Name System )是“域名系统”的英文缩写 正向解析:通过域名查找IP 反向解析:通过IP查找域名 二.安装BIND: BIND即Berkeley In ...

  2. Jenkins的安装和使用

    1.可以参考W3C----https://www.w3cschool.cn/jenkins/jenkins-5h3228n2.html 两种方式安装Jenkins a.安装包 b.Jenkins.wa ...

  3. 转mysql横向扩展和纵向扩展

    Scale-up(纵向扩展)和Scale-out(横向扩展)的解释 谈到系统的可伸缩性,Scale-up(纵向扩展)和Scale-out(横向扩展)是两个常见的术语,对于初学者来说,很容易搞迷糊这两个 ...

  4. 二十六 Python分布式爬虫打造搜索引擎Scrapy精讲—通过downloadmiddleware中间件全局随机更换user-agent浏览器用户代理

    downloadmiddleware介绍中间件是一个框架,可以连接到请求/响应处理中.这是一种很轻的.低层次的系统,可以改变Scrapy的请求和回应.也就是在Requests请求和Response响应 ...

  5. ORM--------Hibernate、Mybatis与Spring Data的区别

    1.概念: Hibernate :Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库.着力点对象 ...

  6. Highcharts 动态图

    Highcharts 动态图 每秒更新曲线图 chart.events chart.event 属性中添加 load 方法(图表加载事件).在 1000 毫秒内随机产生数据点并生成图表. chart: ...

  7. python----tkinterm模块

    python tkinter学习——布局   目录 一.pack() 二.grid() 三.place() 四.Frame() 正文 布局 一.pack() pack()有以下几个常用属性: side ...

  8. Git的三种区域

    Git的区域分为 工作区.缓存区.本地仓库区   我们先看一张图     GitTest是我本地的一个仓库, 其中GitTest目录就是我们的工作区,但不包括.git这个目录 而.git这个目录就是本 ...

  9. 【LeetCode 111_二叉树_遍历】Minimum Depth of Binary Tree

    解法一:递归 int minDepth(TreeNode* root) { if (root == NULL) ; if (root->left == NULL) { ; } else if ( ...

  10. APUE学习笔记——10.11~10.13 信号集、信号屏蔽字、未决信号

    如有转载,请注明出处:Windeal专栏 首先简述下几个概念的关系: 我们通过信号集建立信号屏蔽字,使得信号发生阻塞,被阻塞的信号即未决信号. 信号集: 信号集:其实就是一系列的信号.用sigset_ ...