数据结构: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)指叶结点的最大层树(不包含根结点) 一.树的建立 树可以这样定义:一棵 ...
随机推荐
- HADOOP (十一).安装hbase
下载安装包并解压设置hbase环境变量配置hbase-site.xml启动hbase检测hbase启动情况测试hbase shell 下载安装包并解压 https://mirrors.tuna.tsi ...
- codeforces 319B Psychos in a Line(模拟)
There are n psychos standing in a line. Each psycho is assigned a unique integer from 1 to n. At eac ...
- Java学习个人备忘录之关键字static
被static标记的东西会放在内存中被共享的,对象用到时,就会来取的. class Person { String name; //成员变量,实例变量 static String country = ...
- 11.24Daily Scrum(3)
人员 任务分配完成情况 明天任务分配 王皓南 实现网页上视频浏览的功能.研究相关的代码和功能.1002 数据库测试 申开亮 实现网页上视频浏览的功能.研究相关的代码和功能.1003 实现视频浏览的功能 ...
- ACM 第七天
水题 B - Minimum’s Revenge There is a graph of n vertices which are indexed from 1 to n. For any pair ...
- Qt在VS(Visual Studio)中使用
版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt在VS(Visual Studio)中使用 本文地址:https://www.te ...
- Directory类的使用、Alt+Shift+F10可以查看其命名空间
对于一个对象,按下Alt+Shift+F10可以查看其命名空间. Directory类的使用 using System; using System.Collections.Generic; using ...
- 在select中,载入时默认select为空白,选项内不显示空白项
有两种办法,一种纯css实现,一种借助js实现. html: <body onload="load()"> <select id="abc" ...
- SPD各模块总结
一.用户角色绑定节点 1.库存操作员.库存主管.验货操作员:绑定任一节点 2.采购操作员.公药操作员:只能绑定药库节点 3.退库操作员.药品申领员:绑定药库以外的节点 二.采购计划模块 1.采购计划的 ...
- Signal函数
Signal函数: 这个函数是一种系统调用,就是告诉系统发生中断的时候用该干嘛.第一个参数就是信号的编号,第二个参数就是信号的指针. 原型: #include <signal.h> voi ...