首页 > 其他分享 >[题解] [洛谷P7883] 平面最近点对(加强版)

[题解] [洛谷P7883] 平面最近点对(加强版)

时间:2024-04-12 20:46:12浏览次数:12  
标签:洛谷 加强版 Point int 题解 mid 枚举 double include

[洛谷P1429] 平面最近点对(加强版)

题目描述

给定平面上的 \(n\) 个点,求其中距离最小的两个点之间的距离。

输入格式

第一行: \(n\) ,保证 \(2\leq n \leq 200000\) 。

接下来 \(n\) 行,每行两个实数: \(x, y\),表示一个点的横坐标和纵坐标,中间用一个空格隔开。

输出格式

仅一行,一个实数,表示最短距离,精确到小数点后4位。

题解

如果暴力枚举,则复杂度为 \(O(n^2)\),显然无法通过此题。

考虑分治,将点按照横坐标排序编号后二分区间求解。边界条件是两个编号相同的点或者编号相邻的点,都可以方便的得到它们的距离。问题的关键是合并两个区间时如何计算跨区间的点之间的距离。所谓跨区间,实际上是分布在分割线两侧的点,即 \(x_i < x_{mid}\) 的点和 \(x_i > x_{mid}\) 的点。两两枚举的时间复杂度显然是不行的。

考虑优化。优化的核心是减少枚举次数,即根据一定条件过滤不必要的枚举。因此我们加入枚举条件:假设两个区间内部的最优解是 \(d\) 只枚举距离分割线小于 \(d\) 的部分即可。但这样的时间复杂度依然不够优,因此需要考虑进一步优化。再加入枚举条件: 只计算纵坐标相差小于 \(d\) 的点。可以通过将符合条件的点按照纵坐标排序实现。

如此便可解决此题~

题外话

因为觉得调用sqrt会变慢,我一开始在分治的递归里只算了模没算距离,结果一直两个点TLE,调了半天发现把sqrt放到算模数的那里就行了,可能是double的大数运算太慢了吧... ?

AC代码

#include <algorithm>
#include <iostream>
#include <iomanip>
#include <stack>
#include <cmath>
#define int long long
using namespace std;

const int MAXN = 2e5 + 3;
int n;

class Point {
public:
    double x, y;
} p[MAXN];

inline double getDis(Point a, Point b) {
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

bool cmpX(Point a, Point b) {return a.x < b.x;}
bool cmpY(Point a, Point b) {return a.y > b.y;}

Point tmp[MAXN];
double solve(int l, int r) {
    if (r - l == 1) return getDis(p[l], p[r]);
    int mid = (l + r) >> 1;
    double ans = min(solve(l, mid), solve(mid, r));
    double midx = p[mid].x;
    int cnt = 0;
    for (int i = l; i <= r; i++) {
        if (abs(p[i].x - midx) <= ans) {
            tmp[++cnt] = p[i];
        }
    }
    sort(tmp + 1, tmp + 1 + cnt, cmpY);
    for (int i = 1; i < cnt; i++) {
        for (int j = i + 1; j <= cnt && tmp[i].y - tmp[j].y < ans; j++) {
            ans = min(ans, getDis(tmp[i], tmp[j]));
        }
    }
    return ans;
}

signed main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> p[i].x >> p[i].y;
    }
    sort(p + 1, p + 1 + n, cmpX);
    cout << fixed << setprecision(4) << solve(1, n);
    return 0;
}

标签:洛谷,加强版,Point,int,题解,mid,枚举,double,include
From: https://www.cnblogs.com/Floyd3265/p/18132048

相关文章

  • atcoder beginer 347 (abc347) D E 题解
     D就是二进制下,哪些位置有重合(两个1),哪些位置没有重合(1个1,1个0),剩下的都是0。xor的结果<2^60,就是小于60位(二进制下)。注意要有要求两个数需要是2^60,于是要有大小的判断,因为有的a,b会2^60,但是按照题目要求,这个情况不行。比如xor的结果,60位都是1,然后a、b各有60个1,那么需要有30个1......
  • atcoder beginer 348 (abc348) D E F 题解
     E非常经典的树上操作(树上DP)。父节点到某个子节点,值是如何变化的。1#include<cstdio>2#include<cstdlib>3#include<cstring>4#include<cmath>5#include<cstdbool>6#include<string>7#include<algorithm>8#include<iost......
  • 2024.4.10华为暑期实习笔试题解尝试1~2
    题目在4.10华为暑期实习笔试题解努力开摆的小鱼2024-04-10T1简单难度,按照题意顺着写就可以n=int(input())#表示计费日志的条数lst=[]#去重后的日志ss=set()#为了去重foriinrange(n):s=tuple(input().split(","))t=s[0]+s[1]+s[2]#......
  • 题解:P10320 勇气(Courage)
    P10320勇气(Courage)推导过程本题是一道数学题,重点是如何推导出正确式子。首先,先特判几个特殊点:当\(n>=2\)且\(x=2\)时,是不存在解的,战斗力无论何时都不会超过\(2^{n}\)。当\(x\)不强化就以大于\(2^{n}\)。当\(x\)第一次强化达到\(x^{2}\)时,大于\(2^{n}\)......
  • P4211 LCA 题解
    前置知识:树剖、差分题意给定一个\(n\)个节点的有根树树,根为\(1\)。有\(m\)个询问,每个询问给定\(l,r,z\),求\(\sum\limits_{i=l}^rdep[\textrm{LCA}(i,z)]\)。其中\(dep[x]\)表示\(x\)的深度,有\(dep[1]=1\)。题解式子中的\(dep\)不太好算,考虑转化成形式化......
  • [题解] [NOIP2011] 聪明的质检员
    [NOIP2011]聪明的质监员题目描述小T是一名质量监督员,最近负责检验一批矿产的质量。这批矿产共有\(n\)个矿石,从\(1\)到\(n\)逐一编号,每个矿石都有自己的重量\(w_i\)以及价值\(v_i\)。检验矿产的流程是:给定\(m\)个区间\([l_i,r_i]\);选出一个参数\(W\);对......
  • Qt程序加载Qt platform plugin 'xcb' 出错问题解决
    1.Qt程序运行环境ubuntu16.04Qt5.12.3Qt可执行程序编译后运行Qt可执行程序后出现报错报错内容:qt.qpa.plugin:CouldnotloadtheQtplatformplugin"xcb"in""eventhoughitwasfound.ThisapplicationfailedtostartbecausenoQtplatformplugincouldbe......
  • [题解][2022江西省程序设计竞赛] Graphic Game
    题目描述Cirno被推荐了一个游戏,她决定今天和大妖精一起玩。最初,有一个包含2×n个顶点和m条边的图。在每一轮中,Cirno和大妖精都必须选择一个不同的顶点。所选顶点的度数必须相同。然后,Cirno和大妖精将从图中移除它们。现在Cirno想知道是否有办法从给定的图中移除所有顶点。如果......
  • windows MySQL报错Packet for query is too large问题解决
    1、报错Cause:com.mysql.cj.jdbc.exceptions.PacketTooBigException:Packetforqueryistoolarge(11,792,709>4,194,304).Youcanchangethisvalueontheserverbysettingthe'max_allowed_packet'variable.出现问题的原因:批量插入数据量过大MySQL根据配置......
  • Cunning Gena 题解
    \(\texttt{ProblemLink}\)简要题意翻译很清楚。思路记\(x_i\)表示第\(i\)个人的花费,\(s_i\)表示第\(i\)个人做题集合,\(k_i\)表示第\(i\)个人需要的显示器。\(m\le20\)且不是计数,考虑dp,发现确实可以做。可以设\(f_i\)表示做题集合为\(i\)时最小花费。易......