qwq(明明可以直接分治过掉的)

但是还是当作联系了

首先,对于这种点的题,很显然的套路,我们要维护一个子树\(mx[i],mn[i]\)分别表示每个维度的最大值和最小值

(这里有一个要注意的东西!就是我们\(up\)的时候,要判断一下当前是否还有左/右儿子)

bool operator< (KD a,KD b)
{
return a.d[ymh]<b.d[ymh];
}
void up(int root)
{
for (int i=0;i<=1;i++)
{
if (t[root].l)
{
t[root].mn[i]=min(t[root].mn[i],t[t[root].l].mn[i]);
t[root].mx[i]=max(t[root].mx[i],t[t[root].l].mx[i]);
}
if (t[root].r)
{
t[root].mn[i]=min(t[root].mn[i],t[t[root].r].mn[i]);
t[root].mx[i]=max(t[root].mx[i],t[t[root].r].mx[i]);
}
}
}
void build(int &x,int l,int r,int dd)
{
ymh = dd;
int mid = l+r >> 1;
x = mid;
nth_element(t+l,t+x,t+r+1);
for (int i=0;i<=1;i++) t[x].mn[i]=t[x].mx[i]=t[x].d[i];
if (l<x) build(t[x].l,l,mid-1,dd^1);
if (x<r) build(t[x].r,mid+1,r,dd^1);
up(x);
}

其实这个题最重要的是估价函数该怎么写。

首先我们很容易发现,因为我们要求的是这个子树理论上到那个点的最短距离,所以我们需要这么考虑,如果当前点的坐标在\(mn到mx\)之间的话,那么理论上的最短距离就是0,否则就是当前这一维度距离\(mn和mx\)较近的距离

double calc(KD a,KD b)
{
double tmp=0;
for (int i=0;i<=1;i++)
{
if (b.d[i]<a.mn[i]) tmp=tmp+(a.mn[i]-b.d[i])*(a.mn[i]-b.d[i]);
else if (b.d[i]>a.mx[i]) tmp=tmp+(a.mx[i]-b.d[i])*(a.mx[i]-b.d[i]);
}
return sqrt(tmp);
}

其实剩下的就是和普通的kdtree差不多了

直接上就好了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define mk makr_pair
#define ll long long
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int maxn = 2e5+1e2;
struct KD{
double mx[4],mn[4],d[4];
int l,r;
};
KD t[maxn],now;
int n,m,root;
int ymh;
double ans;
double tmp;
int ii =0;
bool operator< (KD a,KD b)
{
return a.d[ymh]<b.d[ymh];
}
void up(int root)
{
for (int i=0;i<=1;i++)
{
if (t[root].l)
{
t[root].mn[i]=min(t[root].mn[i],t[t[root].l].mn[i]);
t[root].mx[i]=max(t[root].mx[i],t[t[root].l].mx[i]);
}
if (t[root].r)
{
t[root].mn[i]=min(t[root].mn[i],t[t[root].r].mn[i]);
t[root].mx[i]=max(t[root].mx[i],t[t[root].r].mx[i]);
}
}
}
void build(int &x,int l,int r,int dd)
{
ymh = dd;
int mid = l+r >> 1;
x = mid;
nth_element(t+l,t+x,t+r+1);
for (int i=0;i<=1;i++) t[x].mn[i]=t[x].mx[i]=t[x].d[i];
if (l<x) build(t[x].l,l,mid-1,dd^1);
if (x<r) build(t[x].r,mid+1,r,dd^1);
up(x);
}
double getdis(int a,KD b)
{
if (!a) return 0;
double tmp=0;
for (int i=0;i<=1;i++)
{
tmp=tmp+(t[a].d[i]-b.d[i])*(t[a].d[i]-b.d[i]);
}
return sqrt(tmp);
}
double calc(KD a,KD b)
{
double tmp=0;
for (int i=0;i<=1;i++)
{
if (b.d[i]<a.mn[i]) tmp=tmp+(a.mn[i]-b.d[i])*(a.mn[i]-b.d[i]);
else if (b.d[i]>a.mx[i]) tmp=tmp+(a.mx[i]-b.d[i])*(a.mx[i]-b.d[i]);
}
return sqrt(tmp);
}
void query(int x)
{
if (!x) return;
double d1 = calc(t[t[x].l],now);
double d2 = calc(t[t[x].r],now);
double d = getdis(x,now);
if (d<tmp && d!=0) tmp = d;
if (d==0) ii++;
if (d1<d2)
{
if (d1<tmp) query(t[x].l);
if (d2<tmp) query(t[x].r);
}
else
{
if (d2<tmp) query(t[x].r);
if (d1<tmp) query(t[x].l);
}
}
int main()
{
n=read();
for (int i=1;i<=n;i++)
for (int j=0;j<=1;j++) t[i].d[j]=read();
build(root,1,n,0);
tmp = 1e18;
for (int i=1;i<=n;i++)
{
ii=0;
now = t[i];
query(root);
if (ii>1) tmp=0;
}
printf("%.4lf",tmp);
return 0;
}

洛谷1429 平面最近点对(KDTree)的更多相关文章

  1. (洛谷 P1429 平面最近点对(加强版) || 洛谷 P1257 || Quoit Design HDU - 1007 ) && Raid POJ - 3714

    这个讲的好: https://phoenixzhao.github.io/%E6%B1%82%E6%9C%80%E8%BF%91%E5%AF%B9%E7%9A%84%E4%B8%89%E7%A7%8D ...

  2. 洛谷 P1429 平面最近点对(加强版) (分治模板题)

    题意:有\(n\)个点对,找到它们之间的最短距离. 题解:我们先对所有点对以\(x\)的大小进行排序,然后分治,每次左右二等分递归下去,当\(l+1=r\)的时候,我们计算一下距离直接返回给上一层,若 ...

  3. Luogu 1429 平面最近点对 | 平面分治

    Luogu 1429 平面最近点对 题目描述 给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的 输入输出格式 输入格式: 第一行:n:2≤n≤200000 ...

  4. 洛谷P1257 平面上的最接近点对

    n<=10000个点,求欧几里德距离最小的一对点. 经典分治,把这些点按x排序,分成两半,每边分别算答案,答案是左边的最小,右边的最小,左右组起来的最小三者的最小.发现只有左右组的有点难写. 假 ...

  5. 洛谷 P6362 平面欧几里得最小生成树

    题目描述 平面上有 \(n\) 个点,第 \(i\) 个点坐标为 \((x_i, y_i)\).连接 \(i, j\) 两点的边权为 \(\sqrt{(x_i - x_j) ^ 2 + (y_i - ...

  6. 【洛谷P4148】简单题(kd-tree)

    传送门 题意: 给出一个\(n*n\)的棋盘,现在有两种操作:一种是某个格子里的数字加上\(A\),另一种是询问矩阵和. 空间限制:\(20MB\),强制在线. 思路: 直接\(kd-tree\)来搞 ...

  7. 洛谷 P1257 平面上的最接近点对 题解

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

  8. 洛谷 P4148 简单题 KD-Tree 模板题

    Code: //洛谷 P4148 简单题 KD-Tree 模板题 #include <cstdio> #include <algorithm> #include <cst ...

  9. 洛谷4631 [APIO2018] Circle selection 选圆圈 (KD树)

    qwq纪念AC450 一开始想这个题想复杂了. 首先,正解的做法是比较麻烦的. qwqq 那么就不如来一点暴力的东西,看到平面上点的距离的题,不难想到\(KD-Tree\) 我们用类似平面最近点对那个 ...

随机推荐

  1. go GC垃圾回收原理

    目录 1.前言 2. 垃圾回收算法 3. Golang垃圾回收 3.1 垃圾回收原理 3.2 内存标记(Mark) 3.3 三色标记 3.4 Stop The World 4. 垃圾回收优化 4.1 ...

  2. java对象的引用级别

    解释 在java中也有引用的概念,其实就可以认为是变量.标题中的引用级别是指变量与对象之前的引用级别.java中分为4种,按引用强弱关系排序分别是:强引用.软引用.弱引用.虚引用. 强引用(Stron ...

  3. jmeter实际场景应用之测试上传excel文件

    日常工作上测试的时候,会有一些场景是导入/上传文件.我们系统多是excel文件,这里就用excel文件为例,详述一下此次测试遇到的坑.最终结果是成功的,请看到最后! 1.获取接口的一些参数信息 先按F ...

  4. 前后端数据交互(六)——ajax 、fetch 和 axios 优缺点及比较

    一.ajax.fetch 和 axios 简介 1.1.ajax ajax是最早出现发送后端请求的技术,属于原生 js .ajax使用源码,请点击<原生 ajax 请求详解>查看.一般使用 ...

  5. Selenium系列(22) - 通过selenium控制浏览器滚动条的几种方式

    如果你还想从头学起Selenium,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1680176.html 其次,如果你不懂前端基础知识, ...

  6. netfilter框架之hook点

    1. Netfilter中hook的所在位置 当网络上有数据包到来时,由驱动程序将数据包从网卡内存区通过DMA转移到设备主存区(内存区), 之后触发中断通知CPU进行异步响应,之后ip_rcv函数会被 ...

  7. Axis <=1.4 RCE 复现

    1.环境搭建 在idea 上新建项目,然后用tomcat运行即可 2.漏洞复现 2.1 freemarker.template.utility.Execute 如果项目里面没有freemarker 就 ...

  8. 常用CSS的布局问题;

    一.溢出文案省略号显示: //当文字长度超过50px会已省略好的方式显示: width:50px; overflow: hidden; text-overflow: ellipsis; white-s ...

  9. reeswitch http https ws wss nginx domain default port config

    现代H5浏览器产业链越来越丰富,http+websocket+webrtc+sip组合已经是一种非常成熟的web原生音视频通讯解决方案 FreeSWITCH是一个开源的电话软交换平台,早在SIP年代就 ...

  10. 集合Collection ----List集合

    Collection集合体系的特点: set系列集合:添加的元素是 无序,不重复,无索引的 ----HashSet: 无序,不重复,无索引 ----LinkedHashSet: 有序,不重复,无索引 ...