VJ传送门

简要题意:给出两个大小均为\(N\)的点集\(A,B\),试在\(A\)中选择一个点,在\(B\)中选择一个点,使得它们在所有可能的选择方案中欧几里得距离最小,求出这个距离


下面给出的两种解法基本上都能够被卡成\(O(n^2)\)……

按照平面最近点对的做法去做,只是在贡献答案的时候加上所属点集不同的限制就可以了。

当然这个可以卡,只要把\(A\)、\(B\)集合之间分得很开,而\(A\)集合和\(B\)集合内部的点两两之间的距离很小,这样在分治下去的过程中没法贡献答案,最后在分治的第一层就有可能会退化成\(O(n^2)\)

如果你愿意可以旋转坐标系来部分解决上面的问题

代码没有写

K-D Tree

把\(A\)集合的点全部加进去构建K-D Tree,对于\(B\)集合内的每个点在K-D Tree上搜索,加个最优化剪枝。

这个怎么卡应该不需要说了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<algorithm>
#include<cstring>
#include<iomanip>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<vector>
#include<cmath>
#define ld long double
#define int long long
//This code is written by Itst
using namespace std;

inline int read(){
    int a = 0;
    char c = getchar();
    bool f = 0;
    while(!isdigit(c) && c != EOF){
        if(c == '-')
            f = 1;
        c = getchar();
    }
    if(c == EOF)
        exit(0);
    while(isdigit(c)){
        a = a * 10 + c - 48;
        c = getchar();
    }
    return f ? -a : a;
}

const int MAXN = 1e5 + 7;
struct point{
    int x , y , ind;
    point(int _x = 0 , int _y = 0 , int _i = 0):x(_x) , y(_y) , ind(_i){}
}P[MAXN];
int N , rt;
int ch[MAXN][2] , X[MAXN][2] , Y[MAXN][2] , p[MAXN][2];
ld ans;

bool cmp1(point a , point b){
    return a.x == b.x ? a.y < b.y : a.x < b.x;
}

bool cmp2(point a , point b){
    return a.y == b.y ? a.x < b.x : a.y < b.y;
}

inline ld calc(point a , point b){
    return sqrt((long double)(a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}

inline void merge(int x , int y){
    X[x][0] = min(X[x][0] , X[y][0]);
    X[x][1] = max(X[x][1] , X[y][1]);
    Y[x][0] = min(Y[x][0] , Y[y][0]);
    Y[x][1] = max(Y[x][1] , Y[y][1]);
}

int build(int l , int r , bool f){
    if(l > r)
        return 0;
    int mid = (l + r) >> 1;
    nth_element(P + l , P + mid , P + r + 1 , f ? cmp1 : cmp2);
    int t = P[mid].ind;
    X[t][0] = X[t][1] = P[mid].x;
    Y[t][0] = Y[t][1] = P[mid].y;
    if(ch[t][0] = build(l , mid - 1 , f ^ 1))
        merge(t , ch[t][0]);
    if(ch[t][1] = build(mid + 1 , r , f ^ 1))
        merge(t , ch[t][1]);
    return t;
}

inline ld qw(int x , point p){
    int mx = max(max(X[x][0] - p.x , p.x - X[x][1]) , 0ll) , my = max(max(Y[x][0] - p.y , p.y - Y[x][1]) , 0ll);
    return sqrt((long double)mx * mx + my * my);
}

void dfs(int x , point q , bool f){
    if(x == 0 || qw(x , q) > ans)
        return;
    ans = min(ans , calc(point(p[x][0] , p[x][1]) , q));
    if(f ? cmp1(point(p[x][0] , p[x][1]) , q) : cmp2(point(p[x][0] , p[x][1]) , q)){
        dfs(ch[x][1] , q , f ^ 1);
        dfs(ch[x][0] , q , f ^ 1);
    }
    else{
        dfs(ch[x][0] , q , f ^ 1);
        dfs(ch[x][1] , q , f ^ 1);
    }
}

signed main(){
#ifndef ONLINE_JUDGE
    freopen("in","r",stdin);
    freopen("out","w",stdout);
#endif
    for(int T = read() ; T ; --T){
        N = read();
        for(int i = 1 ; i <= N ; ++i){
            P[i].x = p[i][0] = read();
            P[i].y = p[i][1] = read();
            P[i].ind = i;
        }
        rt = build(1 , N , 0);
        ans = 1e50;
        for(int i = 1 ; i <= N ; ++i){
            P[0].x = read();
            P[0].y = read();
            dfs(rt , P[0] , 0);
        }
        cout << fixed << setprecision(3) << ans << endl;
    }
    return 0;
}

POJ3714 Raid 分治/K-D Tree的更多相关文章

  1. poj3714 Raid(分治求平面最近点对)

    题目链接:https://vjudge.net/problem/POJ-3714 题意:给定两个点集,求最短距离. 思路:在平面最近点对基础上加了个条件,我么不访用f做标记,集合1的f为1,集合2的f ...

  2. $Poj3714/AcWing\ Raid$ 分治/平面最近点对

    $AcWing$ $Sol$ 平面最近点对板子题,注意要求的是两种不同的点之间的距离. $Code$ #include<bits/stdc++.h> #define il inline # ...

  3. BZOJ.4182.Shopping(点分治/dsu on tree 树形依赖背包 多重背包 单调队列)

    BZOJ 题目的限制即:给定一棵树,只能任选一个连通块然后做背包,且每个点上的物品至少取一个.求花费为\(m\)时最大价值. 令\(f[i][j]\)表示在点\(i\),已用体积为\(j\)的最大价值 ...

  4. POJ3714 Raid

    Raid Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 10625   Accepted: 3192 Description ...

  5. POJ-3714 Raid 平面最近点对

    题目链接:http://poj.org/problem?id=3714 分治算法修改该为两个点集的情况就可以了,加一个标记... //STATUS:C++_AC_2094MS_4880KB #incl ...

  6. 洛谷P3806 点分治1 & POJ1741 Tree & CF161D Distance in Tree

    正解:点分治 解题报告: 传送门1! 传送门2! 传送门3! 点分治板子有点多,,,分开写题解的话就显得很空旷,不写又不太好毕竟初学还是要多写下题解便于理解 于是灵巧发挥压行选手习惯,开始压题解(bu ...

  7. 【点分治】bzoj1468 Tree

    同poj1741. 换了个更快的姿势,不会重复统计然后再减掉什么的啦~ #include<cstdio> #include<algorithm> #include<cst ...

  8. 【点分治】poj1741 Tree / poj2114 Boatherds / poj1987 Distance Statistics

    三道题都很类似.给出1741的代码 #include<cstdio> #include<algorithm> #include<cstring> using nam ...

  9. 第46届ICPC澳门站 K - Link-Cut Tree // 贪心 + 并查集 + DFS

    原题链接:K-Link-Cut Tree_第46屆ICPC 東亞洲區域賽(澳門)(正式賽) (nowcoder.com) 题意: 要求一个边权值总和最小的环,并从小到大输出边权值(2的次幂):若不存在 ...

随机推荐

  1. loadrunner 运行场景-命令行运行场景

    运行场景-命令行运行场景 by:授客 QQ:1033553122 1 相对路径与绝对路径 在场景中为脚本指定一个相对位置,可以是相对于当前场景目录或lr安装目录. 当你运行一个场景,场景自动从这个相对 ...

  2. Android 高德地图定位

    创建Key 打开高德开发平台 → 我的应用 → 创建应用 → 创建新Key 说明: 1.发布版安全码获取:用自己的签名打包成apk安装软件,用SHA1工具查看 2.调试版安全码获取: 直接运行安装软件 ...

  3. Android View体系(八)从源码解析View的layout和draw流程

    前言 上一篇文章我们讲了View的measure的流程,接下来我们讲下View的layout和draw流程,如果你理解了View的measure的流程,那这篇文章自然就不在话下了. 1.View的la ...

  4. AIOps 一场颠覆传统运维的盛筵

    "颠覆传统运维."是 OneAPM CEO 陈旭经常挂在嘴边的一句话.为什么说 AIOps 将颠覆传统运维?如何才能把人工智能和运维管理相结合并落地? 2018年5月,OneAPM ...

  5. [20180319]直接路径读特例12c.txt

    [20180319]直接路径读特例12c.txt --//昨天的测试突然想起以前遇到的直接路径读特例,在12c重复测试看看. 1.环境:SCOTT@test01p> @ ver1 PORT_ST ...

  6. Win10更换电脑,又不想重装系统的解决方法

    问题描述: 在公司因为两年前用的i3的电脑很卡,然后想换i5的电脑,但是又不想重装系统,因为安装的东西太多了,重装很麻烦 Windows to go介绍: Windows To Go是Windows ...

  7. 5.3Python函数(三)

    目录 目录 前言 (一)装饰器 ==1.简单的装饰器== ==2.修饰带参数函数的装饰器== ==3.修饰带返回值函数的装饰器== ==4.自身带参数的装饰器== (二)迭代器 (三)生成器 ==1. ...

  8. Hbase-2.0.0_04_Hbase原理

    参考博客:Hadoop HBase概念学习系列 参考博客:Hadoop HBase概念学习系列之HBase里的Zookeeper(二十一) 参考博客:Hadoop HBase概念学习系列之HBase里 ...

  9. vue框架简介

    MVVM框架概述 什么是vue 是一套构建用户界面的渐进式(用到哪一块就用哪一块,不需要全部用上)前端框架,Vue 的核心库只关注视图层 vue的兼容性 Vue.js 不支持 IE8 及其以下版本,因 ...

  10. 控件布局_LinearLayout的嵌套

    import android.os.Bundle; import android.app.Activity; public class Layout03 extends Activity { @Ove ...