kdtree学习记录
【转载请注明来自 Galaxies的博客:http://cnblogs.com/galaxies】
这篇文章当做一个记录啦qwq
参考:《K-D Tree在信息学竞赛中的应用》(n+e, 2016-07-31)
一棵二叉树(类似于BST二叉排序树)来维护一个k维空间。每个节点表示的是一个k维空间的区域。
每个节点还存储这一个具体的点,以它的某个坐标来划分出两个k维的空间,为这个节点的儿子所代表的区域。
我们姑且称这个具体的点为代表点。
啥意思呢?
struct node {
int d[K], mx[K], mi[K], l, r;
...
};
d[K]表示这个节点的代表点。这个节点存储的信息是一个K维空间:
第1维 [mi[0], mx[0]];第2维 [mi[1], mx[1]];...;第K维 [mi[K], mx[K]]
l和r存储的是按照代表点的某个坐标来进行划分的两个k维的空间。
为了使得区间平均,我们通常采用按照每个坐标轮流划分。
比如:平面,那么就是2维空间,依次按照 横、纵、横、纵、……划分
3维空间,依次按照 横、纵、高、横、纵、高、……划分
这样可以使得划分出来的空间尽量平均。
比如一个平面的划分方案如下,右图为对应的K-D Tree
划分的过程中,我们需要找到一个代表点,这个代表点通常选取按用来划分的坐标排序的中位数这个点。
STL有一个方便的nth_element可以实现这个功能。
构造应该比较简单?不放代码啦。
然后是插入一个点。
从根往下比较,跟BST类似,就能找到插入的位置了。
下面是一个二维的示范,up里面可以维护信息,“。。。”里面就是把信息扔到K-D Tree的过程。
以下代码如果没有特别说明,ls为T[x].l;rs为T[x].r(预define了)
inline void insert(int &x, int d) {
if(!x) {
x = ++siz;
T[x].d[] = T[x].mi[] = T[x].mx[] = tmp.d[];
T[x].d[] = T[x].mi[] = T[x].mx[] = tmp.d[];
}
if(tmp == T[x]) {
...
return ;
}
if(tmp.d[d] < T[x].d[d]) insert(ls, d^);
else insert(rs, d^);
up(x);
}
然后你需要查询一个k维空间的值,就看是否完全包含/完全不包含
如果以上两类都可以直接回答。否则递归。
inline int query(int x, int x1, int y1, int x2, int y2) {
if(!x) return ;
int ret = ;
if(in(x1, y1, x2, y2, T[x].mi[], T[x].mi[], T[x].mx[], T[x].mx[])) return ...
if(out(x1, y1, x2, y2, T[x].mi[], T[x].mi[], T[x].mx[], T[x].mx[])) return ;
if(in(x1, y1, x2, y2, T[x].d[], T[x].d[], T[x].d[], T[x].d[])) ret += ...;
ret += query(ls, x1, y1, x2, y2) + query(rs, x1, y1, x2, y2);
return ret;
}
上面是一个二维的例子,“。。。”里面可以自行维护需要的东西。
然后我们发现如果K-D Tree的一个区间被插入了好多次那么复杂度会退化(BST没有带平衡)
解决这个问题的办法有两个:
一个比较暴力,就是我的K-D Tree的节点个数达到阈值SIZE的整数倍的时候,就把K-D Tree的节点拎出来,重构K-D Tree即可。
阈值3000-10000(大概
这是一个二维的例子,t里存的是拎出来的旧节点。
inline int rebuild(int l, int r, int d) {
if(l>r) return ;
int mid = l+r>>; D = d;
nth_element(t+l, t+mid, t+r+);
T[mid] = t[mid];
T[mid].l = rebuild(l, mid-, d^);
T[mid].r = rebuild(mid+, r, d^);
up(mid);
return mid;
}
还有一个办法,就是
这个复杂度是对的,就是写起来还要多维护一个size,我这么懒的人肯定是留着坑以后再说啊。。
(不过前面一个复杂度也是对的吧)
对于一些问题的估价:
比如我要询问(x,y)到平面上哪个点欧几里得距离最小啊之类的。
距离最小:一个点离当前域的最小距离(在域内为0)
距离最大:一个点离当前域的最大距离
常见估价:(可以理解)
那么询问(x,y)离哪个点xx距离最小的话。。
就是看看估价,优先访问估价低的。如果最小可能距离都比当前答案大,就不用取管了。
复杂度O(logn)(随机),O(根号n)(构造)
kdtree估价例题:http://www.cnblogs.com/galaxies/p/bzoj2648.html
反正。。挺优秀的。
K-D Tree还可以代替很多类似什么三维偏序啊之类的为题
K维K-D Tree的查询复杂度约为O(n^(1-1/k))
那么可持久化树套树(三维空间的求值)就能在O(n^(5/3))的时间内求出来啊!
论写优秀暴力的重要性。
好了大概讲这么多(去睡觉啦qwq
有空再更
kdtree学习记录的更多相关文章
- Quartz 学习记录1
原因 公司有一些批量定时任务可能需要在夜间执行,用的是quartz和spring batch两个框架.quartz是个定时任务框架,spring batch是个批处理框架. 虽然我自己的小玩意儿平时不 ...
- Java 静态内部类与非静态内部类 学习记录.
目的 为什么会有这篇文章呢,是因为我在学习各种框架的时候发现很多框架都用到了这些内部类的小技巧,虽然我平时写代码的时候基本不用,但是看别人代码的话至少要了解基本知识吧,另外到底内部类应该应用在哪些场合 ...
- Apache Shiro 学习记录4
今天看了教程的第三章...是关于授权的......和以前一样.....自己也研究了下....我觉得看那篇教程怎么说呢.....总体上是为数不多的精品教程了吧....但是有些地方确实是讲的太少了.... ...
- UWP学习记录12-应用到应用的通信
UWP学习记录12-应用到应用的通信 1.应用间通信 “共享”合约是用户可以在应用之间快速交换数据的一种方式. 例如,用户可能希望使用社交网络应用与其好友共享网页,或者将链接保存在笔记应用中以供日后参 ...
- UWP学习记录11-设计和UI
UWP学习记录11-设计和UI 1.输入和设备 通用 Windows 平台 (UWP) 中的用户交互组合了输入和输出源(例如鼠标.键盘.笔.触摸.触摸板.语音.Cortana.控制器.手势.注视等)以 ...
- UWP学习记录10-设计和UI之控件和模式7
UWP学习记录10-设计和UI之控件和模式7 1.导航控件 Hub,中心控件,利用它你可以将应用内容整理到不同但又相关的区域或类别中. 中心的各个区域可按首选顺序遍历,并且可用作更具体体验的起始点. ...
- UWP学习记录9-设计和UI之控件和模式6
UWP学习记录9-设计和UI之控件和模式6 1.图形和墨迹 InkCanvas是接收和显示墨迹笔划的控件,是新增的比较复杂的控件,这里先不深入. 而形状(Shape)则是可以显示的各种保留模式图形对象 ...
- UWP学习记录8-设计和UI之控件和模式5
UWP学习记录8-设计和UI之控件和模式5 1.日历.日期和时间控件 日期和时间控件提供了标准的本地化方法,可供用户在应用中查看并设置日期和时间值. 有四个日期和时间控件可供选择,选择的依据如下: 日 ...
- UWP学习记录7-设计和UI之控件和模式4
UWP学习记录7-设计和UI之控件和模式4 1.翻转视图 使用翻转视图浏览集合中的图像或其他项目(例如相册中的照片或产品详细信息页中的项目),一次显示一个项目. 对于触摸设备,轻扫某个项将在整个集合中 ...
随机推荐
- 剖析DI
0x00.前言 当我们研究一些晦涩的源码,上网查阅资料的时候,映入眼帘的总有这么些名词:DIP.IOC.DI.DL.IOC容器这些专业名词.如果不懂这些名词背后的含义,我们内心有可能是这样的: 0x0 ...
- vs调试代码的时候断点无法命中
https://blog.csdn.net/xxdddail/article/details/18696399 该链接提供的解决方案主要是如下图片:禁用 图片标记的这个选项即可:
- 【vim环境配置】解决ubuntu上 由YouCompleteMe插件配置不当引起的 自动补全失效的问题
背景: 由于不可抗拒的原因,学习环境由之前centos的一台机器上,变成了ubuntu的一台机器上.因此,需要在新的ubuntu的机器上再配置一次vim环境.算起来这已经是第三次配置vim环境了(ma ...
- 今日Linux下安装部署禅道
我的linux系统是在虚拟机上安装的Ubuntu,禅道在官网www.zentao.net下载安装的开源版的linux64位,采用一键安装包安装.安装前要求:系统上不能有自己安装的mysql .下载的安 ...
- c# 对List<T> 某字段排序,取TOP条数据
//排序的对象里的字段数据准备 try { cmr.v4 = Double.Parse(cmr.v3) - Double.Parse(cmr.v2); } catch (Exception e) { ...
- 简易cmake多文件多目录工程模板
今天心血来潮,想在服务器上试试写libevent的工程是什么感受,那第一步就是学会怎么用cmake建工程,之前也没接触过cmake,然后一上午,比较懵逼,下午看实验室哥们给的一个教程,然后,慢慢理解C ...
- 官方文档 恢复备份指南七 Using Flashback Database and Restore Points
本章内容: Understanding Flashback Database, Restore Points and Guaranteed Restore Points Logging for Fla ...
- BZOJ 4184 shallot 线性基+分治
Description 小苗去市场上买了一捆小葱苗,她突然一时兴起,于是她在每颗小葱苗上写上一个数字,然后把小葱叫过来玩游戏. 每个时刻她会给小葱一颗小葱苗或者是从小葱手里拿走一颗小葱苗,并且让小葱从 ...
- 软工实践Beta冲刺(3/7)
队名:起床一起肝活队 组长博客:博客链接 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去两天完成了哪些任务 描述: 1.界面的修改与完善 展示GitHub当日代码/文档签入记 ...
- Java课程设计--学生成绩管理系统
一.团队名称: 团队成员 林艺薇 201721123032 网络1712 黄毓颖 201721123033 网络1712 唐川 201721123034 网络1712 梁才玉 201721123038 ...