KD-tree(2维)
用于动态插入以及求某点的最近点的距离(BZOJ2648,BZOJ2716)
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std; int cnt,ans,n,m; struct data{
int x,y;
}point[]; struct kd_node{
int x,y,lc,rc,minx,miny,maxx,maxy;
}tr[]; int dis(int x1,int y1,int x2,int y2){
return(fabs(x1-x2)+fabs(y1-y2));
} int mycomp1(const data&a,const data&b){
return(a.y<b.y);
} int mycomp2(const data&a,const data&b){
return(a.x<b.x);
} void kd_update(int po){
if (tr[po].lc){
tr[po].minx=min(tr[po].minx,tr[tr[po].lc].minx);
tr[po].miny=min(tr[po].miny,tr[tr[po].lc].miny);
tr[po].maxx=max(tr[po].maxx,tr[tr[po].lc].maxx);
tr[po].maxy=max(tr[po].maxy,tr[tr[po].lc].maxy);
};
if (tr[po].rc){
tr[po].minx=min(tr[po].minx,tr[tr[po].rc].minx);
tr[po].miny=min(tr[po].miny,tr[tr[po].rc].miny);
tr[po].maxx=max(tr[po].maxx,tr[tr[po].rc].maxx);
tr[po].maxy=max(tr[po].maxy,tr[tr[po].rc].maxy);
}
}//维护包含子树中所有点的最小的矩形,左下角(minx,miny),右上角(maxx,maxy) void kd_build(int l,int r,int wd){
if (wd) sort(point+l,point+r+,mycomp1);else sort(point+l,point+r+,mycomp2);//实际应选取方差最大的一维
cnt++;
int mid=(l+r)>>,t=cnt;//mid实际应为与平均值最接近的
tr[cnt].x=point[mid].x;tr[cnt].y=point[mid].y;
tr[cnt].minx=point[mid].x;tr[cnt].maxx=point[mid].x;
tr[cnt].miny=point[mid].y;tr[cnt].maxy=point[mid].y;
if (l<mid){
tr[t].lc=cnt+;kd_build(l,mid-,!wd);
};
if (mid<r){
tr[t].rc=cnt+;kd_build(mid+,r,!wd);
}
kd_update(t);
}//构建n点的KD树,每次以一维为标准划分点 void kd_ins(int po,int x,int y,int d){
int son=;
if (d==) son=(x<=tr[po].x);else son=(y<=tr[po].y);
if (son==){
if (tr[po].lc==){
tr[po].lc=++cnt;
tr[cnt].x=x;tr[cnt].y=y;
tr[cnt].minx=x;tr[cnt].maxx=x;
tr[cnt].miny=y;tr[cnt].maxy=y;
}else kd_ins(tr[po].lc,x,y,!d);
}else{
if (tr[po].rc==){
tr[po].rc=++cnt;
tr[cnt].x=x;tr[cnt].y=y;
tr[cnt].minx=x;tr[cnt].maxx=x;
tr[cnt].miny=y;tr[cnt].maxy=y;
}else kd_ins(tr[po].rc,x,y,!d);
}
kd_update(po);
} int dist(int x,int y,int po){
int ret=;
ret+=max(,tr[po].minx-x);
ret+=max(,x-tr[po].maxx);
ret+=max(,tr[po].miny-y);
ret+=max(,y-tr[po].maxy);
return(ret);
}//(x,y)到po子树维护的矩形的最近距离。假设该矩形中铺满点,所以返回值小于等于实际值 void kd_query(int po,int x,int y){
ans=min(ans,dis(x,y,tr[po].x,tr[po].y));
int dl=(tr[po].lc== ? 1e9:dist(x,y,tr[po].lc));
int dr=(tr[po].rc== ? 1e9:dist(x,y,tr[po].rc));
if (dl<dr){
if (dl<ans) kd_query(tr[po].lc,x,y);
if (dr<ans) kd_query(tr[po].rc,x,y);
}else{
if (dr<ans) kd_query(tr[po].rc,x,y);
if (dl<ans) kd_query(tr[po].lc,x,y);
}
}//以dist为估价函数搜寻 int main(){
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++) scanf("%d%d",&point[i].x,&point[i].y);
kd_build(,n,); for (int i=;i<=m;i++){
int opt,x,y;
scanf("%d%d%d",&opt,&x,&y); if (opt==){
kd_ins(,x,y,);
}else{
ans=1e9;
kd_query(,x,y);
printf("%d\n",ans);
}
}
}
____________________________________________
BZOJ4066
单点修改,矩形求和
#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std; int cnt,tcnt,n; struct data{
int x,y,v;
}a[]; struct treenode{
int lc,rc,x,y,minx,miny,maxx,maxy,num,v;
}tr[]; void update(int po){
tr[po].num=tr[tr[po].lc].num+tr[tr[po].rc].num+tr[po].v;
tr[po].minx=min(min(tr[tr[po].lc].minx,tr[tr[po].rc].minx),tr[po].x);
tr[po].miny=min(min(tr[tr[po].lc].miny,tr[tr[po].rc].miny),tr[po].y);
tr[po].maxx=max(max(tr[tr[po].lc].maxx,tr[tr[po].rc].maxx),tr[po].x);
tr[po].maxy=max(max(tr[tr[po].lc].maxy,tr[tr[po].rc].maxy),tr[po].y);
} void insert(int po,int x,int y,int num,int wd){
if (tr[po].x==x&&tr[po].y==y){
tr[po].num+=num;tr[po].v+=num;return;
} int sel;
if (!wd) sel=(tr[po].x<x);else sel=(tr[po].y<y);
if (!sel){
if (!tr[po].lc){
cnt++;
tr[cnt].x=tr[cnt].minx=tr[cnt].maxx=x;
tr[cnt].y=tr[cnt].miny=tr[cnt].maxy=y;
tr[cnt].v=tr[cnt].num=num;
tr[po].lc=cnt;
update(po);
}else insert(tr[po].lc,x,y,num,!wd);
}else{
if (!tr[po].rc){
cnt++;
tr[cnt].x=tr[cnt].minx=tr[cnt].maxx=x;
tr[cnt].y=tr[cnt].miny=tr[cnt].maxy=y;
tr[cnt].v=tr[cnt].num=num;
tr[po].rc=cnt;
update(po);
}else insert(tr[po].rc,x,y,num,!wd);
}
update(po);
} int mycomp1(const data&a,const data&b){
return(a.x<b.x);
} int mycomp2(const data&a,const data&b){
return(a.y<b.y);
} void build(int l,int r,int wd){
if (wd==) sort(a+l,a+r+,mycomp1);else sort(a+l,a+r+,mycomp2);
int mid=(l+r)>>;
int tmp=++tcnt;
tr[tcnt].lc=tr[tcnt].rc=;
tr[tcnt].x=a[mid].x;tr[tcnt].y=a[mid].y;tr[tcnt].v=a[mid].v;
if (l<mid){
tr[tmp].lc=tcnt+;build(l,mid-,!wd);
};
if (r>mid){
tr[tmp].rc=tcnt+;build(mid+,r,!wd);
}
update(tmp);
} int in(int x1,int y1,int x2,int y2,int X1,int Y1,int X2,int Y2){
return(X1<=x1&&Y1<=y1&&X2>=x2&&Y2>=y2);
} int out(int x1,int y1,int x2,int y2,int X1,int Y1,int X2,int Y2){
return(x2<X1||x1>X2||y1>Y2||y2<Y1);
} int query(int po,int x1,int y1,int x2,int y2){
int ret=;
if (in(tr[po].minx,tr[po].miny,tr[po].maxx,tr[po].maxy,x1,y1,x2,y2)) return(tr[po].num); if (in(tr[po].x,tr[po].y,tr[po].x,tr[po].y,x1,y1,x2,y2)) ret+=tr[po].v;
if (!out(tr[tr[po].lc].minx,tr[tr[po].lc].miny,tr[tr[po].lc].maxx,tr[tr[po].lc].maxy,x1,y1,x2,y2)) ret+=query(tr[po].lc,x1,y1,x2,y2);
if (!out(tr[tr[po].rc].minx,tr[tr[po].rc].miny,tr[tr[po].rc].maxx,tr[tr[po].rc].maxy,x1,y1,x2,y2)) ret+=query(tr[po].rc,x1,y1,x2,y2);
return(ret);
} int main(){
scanf("%d",&n);
tr[].miny=tr[].minx=1e9;
tr[].maxx=tr[].maxy=-1e9;
int opt,lastans=,lastrebuild=,root=;
while (scanf("%d",&opt),opt!=){
int x,y,x1,y1,x2,y2,num; if (opt==){
scanf("%d%d%d",&x,&y,&num);
x^=lastans;y^=lastans;num^=lastans;
if (!root){
root=;
cnt++;
tr[cnt].x=tr[cnt].minx=tr[cnt].maxx=x;
tr[cnt].y=tr[cnt].miny=tr[cnt].maxy=y;
tr[cnt].v=tr[cnt].num=num;
}else{
insert(root,x,y,num,);
} if (cnt/>lastrebuild){
for (int i=;i<=cnt;i++) a[i].x=tr[i].x,a[i].y=tr[i].y,a[i].v=tr[i].v;
tcnt=;
build(,cnt,);
lastrebuild++;
}
} if (opt==){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x1^=lastans;x2^=lastans;y1^=lastans;y2^=lastans;
lastans=query(,x1,y1,x2,y2);
printf("%d\n",lastans);
}
}
}
KD-tree(2维)的更多相关文章
- Wannafly Winter Camp 2020 Day 5I Practice for KD Tree - 二维线段树
给定一个 \(n \times n\) 矩阵,先进行 \(m_1 \leq 5e4\) 次区间加,再进行 \(m_2 \leq 5e5\) 次询问,每次询问要求输出矩形区间内的最大数.\(n \leq ...
- k-d tree 学习笔记
以下是一些奇怪的链接有兴趣的可以看看: https://blog.sengxian.com/algorithms/k-dimensional-tree http://zgjkt.blog.uoj.ac ...
- k-d tree算法
k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据结构.主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索). 应用背景 SIFT算法中做特征点匹配的时候就会利用到k ...
- [模板] K-D Tree
K-D Tree K-D Tree可以看作二叉搜索树的高维推广, 它的第 \(k\) 层以所有点的第 \(k\) 维作为关键字对点做出划分. 为了保证划分均匀, 可以以第 \(k\) 维排名在中间的节 ...
- HDU2966 In case of failure(浅谈k-d tree)
嘟嘟嘟 题意:给定\(n\)个二维平面上的点\((x_i, y_i)\),求离每一个点最近的点得距离的平方.(\(n \leqslant 1e5\)) 这就是k-d tree入门题了. k-d tre ...
- [学习笔记]K-D Tree
以前其实学过的但是不会拍扁重构--所以这几天学了一下 \(K-D\ Tree\) 的正确打开姿势. \(K\) 维 \(K-D\ Tree\) 的单次操作最坏时间复杂度为 \(O(k\times n^ ...
- BZOJ 3053: The Closest M Points(K-D Tree)
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1235 Solved: 418[Submit][Status][Discuss] Descripti ...
- 浅谈K-D Tree
初步认识\(K-D\) \(Tree\) \(K-D\) \(Tree\)是一种基于空间分割的二叉树形数据结构,一般用于高维信息检索.因为\(OI\)中很多问题都能转化为高维信息检索,所以\(K-D\ ...
- K-D TREE算法原理及实现
博客转载自:https://leileiluoluo.com/posts/kdtree-algorithm-and-implementation.html k-d tree即k-dimensional ...
- [转载]kd tree
[本文转自]http://www.cnblogs.com/eyeszjwang/articles/2429382.html k-d树(k-dimensional树的简称),是一种分割k维数据空间的数据 ...
随机推荐
- C# 3.0新语言特性和改进(一)
引言 关于C#3.0的特性,园子里已经有了一大把,可能大家都很熟悉了,虽然本人开发中使用过,但自己还是需要记录一下,总结一下.同时也是后面写Linq知识的基础.希望有兴趣的朋友,可以看看. C# 3. ...
- 全局变量:global与$GLOBALS的区别和使用
今天在写框架的时候想把SaeMySQL初始化之后作为全局变量使用.但是后来发现PHP中的全局变量和Java或者OC中的全局变量还是有较大区别的.下面记录一下php里面的global的使用相关注意事项. ...
- C# - 多线程 之 进程与线程
并行~并发 并发 Concurrency,逻辑上的同时发生,一个处理器(在不同时刻或者说在同一时间间隔内)"同时"处理多个任务.宏观上是并发的,微观上是按排队等待.唤醒.执行的步骤 ...
- bzoj1001--最大流转最短路
http://www.lydsy.com/JudgeOnline/problem.php?id=1001 思路:这应该算是经典的最大流求最小割吧.不过题目中n,m<=1000,用最大流会TLE, ...
- ExtPB.Net:窗体应用技巧(2)在树形导航下打开弹出的win窗口
ExtPB.Net的demo程序有个树形导航菜单,里面的菜单打开的窗口放在右边的TabStrip控件中.我们可以设计win通过导航打开,但有时我们希望以弹出窗口的形式打开它,但怎么办呢?现在可以这样修 ...
- 第三方开源库和jar包的区别
jar包和第三方开源库的根本区别在于,开源库的功能比jar包功能更强大,通过引入库项目可以访问java文件以及该开源库项目下的资源文件,例如图片,layout等文件 jar包中只能放class文件 引 ...
- 慎用mutableCopy
因为逻辑需要,我在present到一个页面时,将一个存放uiimage的数组mutablecopy了过去(因为再返回的时候防止对数组做了改动),时间长了也忘了这事儿,后来发现添加多张图片上传时,app ...
- SVN为什么比Git更好
首先我表明一个根本的立场,我个人更喜欢用Git,但是,这仅仅是一个个人偏好.当我们需要将一种技术方案带给整个团队的时候,并不是由我们的个人偏好作为主要决定因素,而应该充分去权衡利弊,选择对团队,对公司 ...
- 一个基于Microsoft Azure、ASP.NET Core和Docker的博客系统
2008年11月,我在博客园开通了个人帐号,并在博客园发表了自己的第一篇博客.当然,我写博客也不是从2008年才开始的,在更早时候,也在CSDN和系统分析员协会(之后名为“希赛网”)个人空间发布过一些 ...
- Linux下命令行安装weblogic10.3.6
Linux下命令行安装weblogic10.3.6 一.安装前准备工作: 1.创建用户useradd weblogic;创建用户成功linux系统会自动创建一个和用户名相同的分组,并将该用户分到改组中 ...