当前位置: 首页 > news >正文

KD-Tree 学习笔记

申请加入跑不满算法协会。

用于维护多维信息的 Unleafy Tree。

1 建树

每个节点维护一个矩阵的信息,具体的,需要记录矩阵内的横纵坐标最值。

建树时对当前点的矩阵横着竖着轮流切,中间的点作为该节点的权值,对于切下来的矩阵接着递归建树。

int cnt=0;
struct{int ls,rs,v[2],mn[2],mx[2];
}tr[200200];
#define mid ((l+r)>>1)
#define ls(x) tr[x].ls
#define rs(x) tr[x].rs
#define v(x,p) tr[x].v[p]
#define mn(x,p) tr[x].mn[p]
#define mx(x,p) tr[x].mx[p]
void up(int id){for(int i=0;i<2;i++){mn(id,i)=mx(id,i)=v(id,i);if(ls(id)){mn(id,i)=min(mn(id,i),mn(ls(id),i));mx(id,i)=max(mx(id,i),mx(ls(id),i));}if(rs(id)){mn(id,i)=min(mn(id,i),mn(rs(id),i));mx(id,i)=max(mx(id,i),mx(rs(id),i));}}
}
void build(int &id,int l,int r,int fl){if(l>r){id=0;return;}nth_element(a+l,a+mid,a+1+r,[fl](Murasame x,Murasame y){return x.v[fl]<y.v[fl];});id=++cnt;v(id,0)=a[mid].v[0],v(id,1)=a[mid].v[1];build(ls(id),l,mid-1,fl^1);build(rs(id),mid+1,r,fl^1);up(id);
}

2 邻域查询

邻域查询指查询最近/远点。

这是 \(O(n)\) 的,但是很多题不卡能草过一坨点,接下来以查询最远点为例。

考虑如果一个节点矩阵里查询点的最远距离也比答案要小,那么就不需要递归该节点。

设计一个加权函数表示节点矩阵里查询点的最远距离,递归时优先递归加权值更大的子树。

想不到魔怔话于是用这句话代替。

//ans2 为当前的答案。
int fmax(int id,int x,int y){int ans=0;ans+=max(abs(x-mn(id,0)),abs(x-mx(id,0)));ans+=max(abs(y-mx(id,1)),abs(y-mn(id,1)));return ans;
}
void qmax(int id,int x,int y){if(!id) return;ans2=max(ans2,abs(v(id,0)-x)+abs(v(id,1)-y));int vl=-2e9,vr=-2e9;if(ls(id)) vl=fmax(ls(id),x,y);if(rs(id)) vr=fmax(rs(id),x,y);if(vl>vr){if(vl>ans2) qmax(ls(id),x,y);if(vr>ans2) qmax(rs(id),x,y);} else{if(vr>ans2) qmax(rs(id),x,y);if(vl>ans2) qmax(ls(id),x,y);}
}

3 矩阵查询

Q:丛雨和 0d00 的共同点?。

像线段树一样,完全被查询区间包含就返回整个矩阵,相离就返回滚木,否则接着往下递归。

有精细证明该操作复杂度为单次 \(O(n^{1-\frac{1}{k}})\) 的,其中 \(k\) 为维数,但该证明需要主定理我不会😅。

int query(int id,int x1,int y1,int x2,int y2){if(!id) return 0;if(x1<=mn(id,0)&&y1<=mn(id,1)&&x2>=mx(id,0)&&y2>=mx(id,1)) return sz(id);//被完全包含if(x1> mx(id,0)||y1> mx(id,1)||x2< mn(id,0)||y2< mn(id,1)) return 0;//相离int fl=(x1<=v(id,0)&&y1<=v(id,1)&&x2>=v(id,0)&&y2>=v(id,1));//自身是否在查询矩阵内return query(ls(id),x1,y1,x2,y2)+query(rs(id),x1,y1,x2,y2)+fl;
} 

4 查询一次函数下/上侧信息

丛雨并没有重力所以叫将臣起床施加的压力是来自……?。

照着矩阵查询的样子瞎写写就好了,复杂度伪的别管。

bool check(int x,int y,double k,double b,bool fl){//点是否在上/下侧return fl?(y>x*k+b):(y<x*k+b);
}
bool checkN(int id,double k,double b,bool fl){//矩阵是否完全不在上/下侧if(check(mn(id,0),mn(id,1),k,b,fl)) return 0;if(check(mx(id,0),mn(id,1),k,b,fl)) return 0;if(check(mn(id,0),mx(id,1),k,b,fl)) return 0;if(check(mx(id,0),mx(id,1),k,b,fl)) return 0;return 1;
}
bool checkA(int id,double k,double b,bool fl){//矩阵是否完全在上/下侧if(!check(mn(id,0),mn(id,1),k,b,fl)) return 0;if(!check(mx(id,0),mn(id,1),k,b,fl)) return 0;if(!check(mn(id,0),mx(id,1),k,b,fl)) return 0;if(!check(mx(id,0),mx(id,1),k,b,fl)) return 0;return 1;
}
int que(int id,double k,double b,bool fl){if(!id) return 0;if(checkN(id,k,b,fl)) return 0;if(checkA(id,k,b,fl)) return sum(id);return que(ls(id),k,b,fl)+que(rs(id),k,b,fl)+val(id)*check(v(id,0),v(id,1),k,b,fl);//记得加自身贡献
}

5 求第 k 远点

受不了了太魔怔了不写了。

拿个优先队列存下前 k 远就行了,估价函数直接抄最远的就行了,如果权值比当前第 k 远小就不进行递归。

提前往优先队列里放 k 个 -1 能省掉一些细节。

int fmax(int id,int x,int y){int ans=0;ans+=max(abs(x-mn(id,0)),abs(x-mx(id,0)))*max(abs(x-mn(id,0)),abs(x-mx(id,0)));ans+=max(abs(y-mx(id,1)),abs(y-mn(id,1)))*max(abs(y-mx(id,1)),abs(y-mn(id,1)));return ans;
}
void qmax(int id,int x,int y){if(!id) return;q.push({dis(v(id,0),v(id,1),x,y),p(id)});q.pop();int vl=-2e9,vr=-2e9,ans=q.top().val;if(ls(id)) vl=fmax(ls(id),x,y);if(rs(id)) vr=fmax(rs(id),x,y);if(vl>vr){if(vl>=ans) qmax(ls(id),x,y);if(vr>=ans) qmax(rs(id),x,y);} else{if(vr>=ans) qmax(rs(id),x,y);if(vl>=ans) qmax(ls(id),x,y);}
}
http://www.jsqmd.com/news/518538/

相关文章:

  • 手把手教你写一个简单的油猴脚本:以实验室安全考试自动答题为例
  • COMSOL光学波导传输仿真 光纤等波导的三维弯曲 模场分布 波束包络方法 FDTD计算模式弯曲损耗
  • 编写程序实现智能快递柜湿度检测,湿度过高,提示“防潮”,保护包裹内物品。
  • 基于YOLOv8/YOLOv10/YOLOv11/YOLOv12与SpringBoot的杂草检测系统(DeepSeek智能分析+web交互界面+前后端分离+YOLO数据)
  • 手把手教你学Simulink——基于Simulink的滑模控制(SMC)抗参数摄动PMSM驱动
  • 避坑指南:QEMU网络桥接配置中,tap0创建失败和br0没IP的常见问题解决
  • PyCharm Community最新版安装避坑指南:从下载到首次运行的完整流程
  • ROS2 CLI命令大全:接口查看与自定义的终极效率指南
  • 基于YOLOv8/YOLOv10/YOLOv11/YOLOv12与SpringBoot的猫狗品种检测系统(DeepSeek智能分析+web交互界面+前后端分离+YOLO数据)
  • 手把手教你学Simulink——基于 Simulink 的 LQR 最优电流跟踪控制器设计
  • 从CSP-S真题看编程竞赛演变:这5类题型占比飙升(附2024最新趋势)
  • 从Midjourney到Sora:多模态生成式AI如何悄悄改变你的工作流?设计师、产品经理必看
  • STM32F030C8T6多通道ADC采集实战:从硬件连接到软件配置全流程解析
  • 手把手教你学Simulink——基于 Simulink 的 基于李雅普诺夫的稳定 DC-DC 控制器
  • 基于YOLOv8/YOLOv10/YOLOv11/YOLOv12与SpringBoot的小目标车辆检测系统(DeepSeek智能分析+web交互界面+前后端分离+YOLO数据)
  • 春运抢票生态观察:当免费工具成为打工人回家的「技术平权」
  • MATLAB环境中应用高分辨率二维时频分析方法——同步压缩小波变换与曲波变换在混合地震数据分离...
  • 基于YOLOv8/YOLOv10/YOLOv11/YOLOv12与SpringBoot的绝缘子缺陷检测系统(DeepSeek智能分析+web交互界面+前后端分离+YOLO数据)
  • Postman 前置脚本实战:动态生成接口签名与参数加密
  • 手机拍照也能玩高光谱?教你用TensorFlow Lite在Android上实现实时RGB转高光谱
  • BasicsLibrary:面向嵌入式初学者的Arduino零门槛硬件交互库
  • 基于YOLOv8/YOLOv10/YOLOv11/YOLOv12与SpringBoot的小麦叶片病害检测系统(DeepSeek智能分析+web交互界面+前后端分离+YOLO数据)
  • BEVFusion实战:如何在nuScenes数据集上快速搭建3D目标检测环境(附常见报错解决方案)
  • Audacity隐藏技巧:用Python脚本批量拆分100+音频文件(Windows/Mac通用)
  • 直齿轮和斜齿轮啮合刚度计算Matlab程序
  • 别再让LLM‘盲猜’了!用MCP Server给你的Java后端开个‘数据接口’
  • Windows平台打造极速Verilog/SystemVerilog开发环境:从零配置到高效编码
  • Altium Designer vs 立创EDA:跨平台封装迁移的3个隐藏技巧
  • 基于YOLOv8/YOLOv10/YOLOv11/YOLOv12与SpringBoot的白细胞类型检测系统(DeepSeek智能分析+web交互界面+前后端分离+YOLO数据)
  • 中国芯片出口额暴涨七成,芯片单价猛涨五成,苦熬终获巨额回报