POJ3714 Raid 分治/K-D Tree
简要题意:给出两个大小均为\(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的更多相关文章
- poj3714 Raid(分治求平面最近点对)
题目链接:https://vjudge.net/problem/POJ-3714 题意:给定两个点集,求最短距离. 思路:在平面最近点对基础上加了个条件,我么不访用f做标记,集合1的f为1,集合2的f ...
- $Poj3714/AcWing\ Raid$ 分治/平面最近点对
$AcWing$ $Sol$ 平面最近点对板子题,注意要求的是两种不同的点之间的距离. $Code$ #include<bits/stdc++.h> #define il inline # ...
- BZOJ.4182.Shopping(点分治/dsu on tree 树形依赖背包 多重背包 单调队列)
BZOJ 题目的限制即:给定一棵树,只能任选一个连通块然后做背包,且每个点上的物品至少取一个.求花费为\(m\)时最大价值. 令\(f[i][j]\)表示在点\(i\),已用体积为\(j\)的最大价值 ...
- POJ3714 Raid
Raid Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 10625 Accepted: 3192 Description ...
- POJ-3714 Raid 平面最近点对
题目链接:http://poj.org/problem?id=3714 分治算法修改该为两个点集的情况就可以了,加一个标记... //STATUS:C++_AC_2094MS_4880KB #incl ...
- 洛谷P3806 点分治1 & POJ1741 Tree & CF161D Distance in Tree
正解:点分治 解题报告: 传送门1! 传送门2! 传送门3! 点分治板子有点多,,,分开写题解的话就显得很空旷,不写又不太好毕竟初学还是要多写下题解便于理解 于是灵巧发挥压行选手习惯,开始压题解(bu ...
- 【点分治】bzoj1468 Tree
同poj1741. 换了个更快的姿势,不会重复统计然后再减掉什么的啦~ #include<cstdio> #include<algorithm> #include<cst ...
- 【点分治】poj1741 Tree / poj2114 Boatherds / poj1987 Distance Statistics
三道题都很类似.给出1741的代码 #include<cstdio> #include<algorithm> #include<cstring> using nam ...
- 第46届ICPC澳门站 K - Link-Cut Tree // 贪心 + 并查集 + DFS
原题链接:K-Link-Cut Tree_第46屆ICPC 東亞洲區域賽(澳門)(正式賽) (nowcoder.com) 题意: 要求一个边权值总和最小的环,并从小到大输出边权值(2的次幂):若不存在 ...
随机推荐
- docker第一章:docker核心概念及centos6下安装
Docker三大核心概念 镜像 容器 仓库 镜像 docker镜像类似于虚拟机镜像,可以将它理解为一个面向Docker引擎的只读模板,包含了文件系统. 容器 1.容器是从镜像创建的应用运行实例,容器和 ...
- Ubuntu中针对问题 E: Could not get lock /var/lib/dpkg/lock - open (11: Resource temporarily unavailable)的解决方案
一.问题描述: 在ubuntu中有时因为错误的操作,而导致在执行 sudo apt-get install xxxx出现如下错误: E: Could not get lock /var/lib/dpk ...
- Tars --- Hello World
服务端开发 1,创建一个 webapp maven 项目,pom.xml 导入依赖 <dependency> <groupId>com.tencent.tars</gro ...
- Expo大作战(三十七)--expo sdk api之 GLView,GestureHandler,Font,Fingerprint,DeviceMotion,Brightness
简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...
- sql server alwayson 可用性组 只读路由的设置
昨天晚上学习了[SQL Server 2012实施与管理实战指南]的第三章,于是今天想在前段时间建的那个alwayson 可用性组测试环境上也配置一下只读路由,尝试实现读写分离. 按照书中的方法,执行 ...
- Linux下的进程类别(内核线程、轻量级进程和用户进程)--Linux进程的管理与调度(四)
本文中出现的,内核线程,轻量级进程,用户进程,用户线程等概念,如果不太熟悉, 可以参见 内核线程.轻量级进程.用户线程三种线程概念解惑(线程≠轻量级进程) Linux进程类别 虽然我们在区分Linux ...
- Python面试题(一)【转】
注:本面试题来源于网络,转载自http://www.cnblogs.com/goodhacker/p/3366618.html. 1. (1)python下多线程的限制以及多进程中传递参数的方式 py ...
- 【问题集】VS新建项目——失败——弹出“未将对象引用设置到对象的实例”
- 【PAT】B1084 外观数列(20 分)(纯C)
第一层循环,用来循环计算第几个元素 第二层用来计算当前元素的下一个 #include<stdio.h> #include<string.h> char aaa[100000] ...
- python 计时累积超过24小时时继续往上累加
最近在做一个工具,要求在工具上面加上程序运行的时间,所以做了个计时器 在网上找了很多发现都是24小时制的,超过24小时后就会回0 然后自己根据24小时制修改了一个不停累加时间的 若是想超过24小时后以 ...