数据结构:K-D树
K-D树实际上是一棵高维二叉搜索树,与普通二叉搜索树不同的是,树中存储的是一些K维数据
普通的二叉搜索树是一维的,当推广到K维后,就是我们的K-D树了
在K-D树中跟二叉搜索树差不多,也是将一个K维的数据与根节点进行比较,然后划分的
这里的比较不是整体的比较,而是选择其中一个维度来进行比较
在K-D树进行划分时,可以每次选择方差最大的属性来划分数据到左右子树
在K-D树的划分中,这个轴的选取很关键,要保证划分后的左右子树尽量平衡
那么很显然选取这个属性的值对应数组的中位数作为pivot
然后是查找了,最邻近查找的算法描述如下
()将查询数据Q从根节点开始,按照Q与各个节点的比较结果向下遍历,直到到达叶子节点为止。 到达叶子节点时,计算Q与叶子节点上保存的所有数据之间的距离,记录最小距离对应的数据点, 假设当前最邻近点为p_cur,最小距离记为d_cur ()进行回溯操作,该操作的目的是找离Q更近的数据点,即在未访问过的分支里,是否还有离Q更近的点 它们的距离小于d_cur
然后一道模板题,BZOJ1941,给出平面上n个点,求距离每个点最大距离减最小距离(不算自己)的最小值
枚举每个点找最近点,最远点更新答案
敲的好累啊!!
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int INF=;
const int mod=;
int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,F,rt,ans=INF;
int x[],y[];
struct P
{
int d[],mn[],mx[],l,r;
int& operator[](int x)
{
return d[x];
}
friend bool operator<(P a,P b)
{
return a[F]<b[F];
}
friend int dis(P a,P b)
{
return abs(a[]-b[])+abs(a[]-b[]);
}
}p[];
struct kdtree
{
P t[],T;
int ans;
void update(int k)
{
int l=t[k].l,r=t[k].r;
for(int i=;i<;i++)
{
t[k].mn[i]=t[k].mx[i]=t[k][i];
if(l) t[k].mn[i]=min(t[k].mn[i],t[l].mn[i]);
if(r) t[k].mn[i]=min(t[k].mn[i],t[r].mn[i]);
if(l) t[k].mx[i]=max(t[k].mx[i],t[l].mx[i]);
if(r) t[k].mx[i]=max(t[k].mx[i],t[r].mx[i]);
}
}
int build(int l,int r,int now)
{
F=now;
int mid=(l+r)>>;
nth_element(p+l,p+mid,p+r+);
t[mid]=p[mid];
for(int i=;i<;i++)
t[mid].mn[i]=t[mid].mx[i]=t[mid][i];
if(l<mid) t[mid].l=build(l,mid-,now^);
if(r>mid) t[mid].r=build(mid+,r,now^);
update(mid);
return mid;
}
int getmn(P a)
{
int ans=;
for(int i=;i<;i++)
{
ans+=max(T[i]-a.mx[i],);
ans+=max(a.mn[i]-T[i],);
}
return ans;
}
int getmx(P a)
{
int ans=;
for(int i=;i<;i++)
ans+=max(abs(T[i]-a.mx[i]),abs(T[i]-a.mn[i]));
return ans;
}
void querymx(int k)
{
ans=max(ans,dis(t[k],T));
int l=t[k].l,r=t[k].r,dl=-INF,dr=-INF;
if(l) dl=getmx(t[l]);if(r) dr=getmx(t[r]);
if(dl>dr)
{
if(dl>ans)querymx(l);
if(dr>ans)querymx(r);
}
else
{
if(dr>ans)querymx(r);
if(dl>ans)querymx(l);
}
}
void querymn(int k)
{
int tmp=dis(t[k],T);
if(tmp)ans=min(ans,tmp);
int l=t[k].l,r=t[k].r,dl=INF,dr=INF;
if(l)dl=getmn(t[l]);if(r)dr=getmn(t[r]);
if(dl<dr)
{
if(dl<ans)querymn(l);
if(dr<ans)querymn(r);
}
else
{
if(dr<ans)querymn(r);
if(dl<ans)querymn(l);
}
}
int query(int f,int x,int y)
{
T[]=x;T[]=y;
if(f==)ans=INF,querymn(rt);
else ans=-INF,querymx(rt);
return ans;
}
}kdtree;
int main()
{
n=read();
for(int i=;i<=n;i++)
{
x[i]=read(),y[i]=read();
p[i][]=x[i];p[i][]=y[i];
}
rt=kdtree.build(,n,);
for(int i=;i<=n;i++)
{
int mn=kdtree.query(,x[i],y[i]),mx=kdtree.query(,x[i],y[i]);
ans=min(ans,mx-mn);
}
printf("%d\n",ans);
return ;
}
数据结构:K-D树的更多相关文章
- 【经典数据结构】B树与B+树
本文转载自:http://www.cnblogs.com/yangecnu/p/Introduce-B-Tree-and-B-Plus-Tree.html 维基百科对B树的定义为“在计算机科学中,B树 ...
- 数据结构---平衡查找树之B树和B+树(转)
本文转载自:http://www.cnblogs.com/yangecnu/p/Introduce-B-Tree-and-B-Plus-Tree.html 前面讲解了平衡查找树中的2-3树以及其实现红 ...
- 【经典数据结构】B树与B+树(转)
本文转载自:http://www.cnblogs.com/yangecnu/p/Introduce-B-Tree-and-B-Plus-Tree.html 维基百科对B树的定义为“在计算机科学中,B树 ...
- 【经典数据结构】B树与B+树的解释
本文转载自:http://www.cnblogs.com/yangecnu/p/Introduce-B-Tree-and-B-Plus-Tree.html 前面讲解了平衡查找树中的2-3树以及其实现红 ...
- 数据结构-PHP 线段树的实现
转: 数据结构-PHP 线段树的实现 1.线段树介绍 线段树是基于区间的统计查询,线段树是一种 二叉搜索树,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点.使用线段树可以快速的查 ...
- D&F学数据结构系列——B树(B-树和B+树)介绍
B树 定义:一棵B树T是具有如下性质的有根树: 1)每个节点X有以下域: a)n[x],当前存储在X节点中的关键字数, b)n[x]个关键字本身,以非降序存放,因此key1[x]<=key2[x ...
- Go 数据结构--二分查找树
Go 数据结构--二分查找树 今天开始一个Go实现常见数据结构的系列吧.有时间会更新其他数据结构. 一些概念 二叉树:二叉树是每个节点最多有两个子树的树结构. 完全二叉树:若设二叉树的高度为h,除第 ...
- Linux 内核中的数据结构:基数树(radix tree)
转自:https://www.cnblogs.com/wuchanming/p/3824990.html 基数(radix)树 Linux基数树(radix tree)是将指针与long整数键值相 ...
- 【BZOJ】3196: Tyvj 1730 二逼平衡树(区间第k小+树套树)
http://www.lydsy.com/JudgeOnline/problem.php?id=3196 Treap+树状数组 1WA1A,好伤心,本来是可以直接1A的,这次开始我并没有看题解,就写出 ...
- Python数据结构应用6——树
数据结构中的树的结点和机器学习中决策树的结点有一个很大的不同就是,数据结构中的树的每个叶结点都是独立的. 树的高度(Height)指叶结点的最大层树(不包含根结点) 一.树的建立 树可以这样定义:一棵 ...
随机推荐
- 4-1:实现tee命令
#include <stdio.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h& ...
- java实现几种简单的排序算法
public class SimpleAri { public static void main(String[] args) { int[] t = {11, 21, 22, 1, 6, 10, 3 ...
- lintcode-170-旋转链表
170-旋转链表 给定一个链表,旋转链表,使得每个节点向右移动k个位置,其中k是一个非负数 样例 给出链表1->2->3->4->5->null和k=2 返回4-> ...
- win7 64位在线编辑dsoframer控件的安装和使用配置
经历了两天的折磨,查阅了网上的资料,按网上的操作试了n种方法结果还是不行,开始以为是dsoframer 是32位控件问题,结果不是(经历了更改解决方案cpu,发布基于x86的网站:以为是操作系统问题, ...
- 移动端调试和fiddler移动端抓包使用
这里介绍一款移动端的调试工具以及抓包工具fiddler的使用.也是初次接触,算是初次接触的总结. 1,移动端调试工具.手机截图如下 代码实现 <!DOCTYPE html> <htm ...
- Android基础------通知栏
前言:Android通知栏提示笔记 通知几乎是每一款app都拥有的功能 1.发送通知 发送一个通知栏必须用到两个类: NotificationManager . Notification. Noti ...
- [C/C++] char data[0](柔性数组)
转自:http://blog.csdn.net/yby4769250/article/details/7294696 在标准C和C++中0长数组如charArray[0]是不允许使用的,因为这从语义逻 ...
- 第50天:scrollTo小火箭返回顶部
scrollTo(x,y)//可把内容滚动到指定的坐标scrollTo(xpos,ypos)//x,y值必需 1.固定导航栏 <!DOCTYPE html> <html lang=& ...
- 第49天:封装自己的scrollTop
一.scroll家族 offset 自己的偏移scroll滚动的 scrollTop和scrollLeftscrollTop 被卷去的头部当滑动滚轮浏览网页的时候,网页隐藏在屏幕上方的距离二.页面滚动 ...
- 同步锁(synchronized)使用三要素
1.代码被多个线程访问 2.代码中有共享的数据 3.共享数据被多个语句操作