[模板] K-D Tree
K-D Tree
K-D Tree可以看作二叉搜索树的高维推广, 它的第 \(k\) 层以所有点的第 \(k\) 维作为关键字对点做出划分.
为了保证划分均匀, 可以以第 \(k\) 维排名在中间的节点为划分节点. 这可以利用 std::nth_element 实现.
K-D Tree 支持单点修改. 为了保证 K-D Tree 的平衡性, 可以利用替罪羊树的思想, 在某个子树不平衡时重构这个子树.
同时, 对于每个点可以代表它所有子节点的 \([min(x_i), max(x_i)]\) 的一块超空间. 因此可以实现区间查询的操作.
根据 Wikipedia 的说法, 区间查询的最坏复杂度为单次 \(O(k \cdot n^{1-\frac 1k})\). (不会证)
其他操作
//to update
Code
//kdt
const int dk=2;
const db alp=0.75;
struct tp{
int v[dk];
int& operator[](int p){return v[p];}
const int& operator[](int p)const{return v[p];}
};
typedef const tp& ctp;
int key;
bool cmp1(ctp a,ctp b){return a[key]<b[key];}
bool eq(ctp a,ctp b){
rep(i,0,dk-1)if(a[i]!=b[i])return 0;
return 1;
}
struct tnd{tp po,mi,mx;int v,sum,sz,ch[2];}tree[nsz];
#define ls(p) tree[p].ch[0]
#define rs(p) tree[p].ch[1]
int rt=0,pt=0;
bool isbad(int p){return tree[ls(p)].sz>tree[p].sz*alp||tree[rs(p)].sz>tree[p].sz*alp;}
void pu(int p){
int l=ls(p),r=rs(p);
tree[p].sum=tree[l].sum+tree[r].sum+tree[p].v;
tree[p].sz=tree[l].sz+tree[r].sz+1;
rep(i,0,dk-1){
tree[p].mi[i]=min(tree[p].po[i],min((l?tree[l].mi[i]:(int)1e9),(r?tree[r].mi[i]:(int)1e9)));
tree[p].mx[i]=max(tree[p].po[i],max((l?tree[l].mx[i]:-1),(r?tree[r].mx[i]:-1)));
}
}
int li[nsz],pl=0;
bool cmp2(int a,int b){return cmp1(tree[a].po,tree[b].po);}
void pia(int rt){
if(ls(rt))pia(ls(rt));
li[++pl]=rt;
if(rs(rt))pia(rs(rt));
}
void build(int &rt,int rl,int rr,int k){
if(rl>rr){rt=0;return;}
int mid=(rl+rr)>>1;
key=k,nth_element(li+rl,li+mid,li+rr+1,cmp2);
rt=li[mid];
build(ls(rt),rl,mid-1,(k+1)%dk);
build(rs(rt),mid+1,rr,(k+1)%dk);
pu(rt);
}
void rebuild(int &rt,int k){
pl=0,pia(rt);
build(rt,1,pl,k);
}
void insert(tp p,int v,int &rt,int k){
if(rt==0){rt=++pt,tree[rt].po=p,tree[rt].v=v,pu(rt);return;}
if(eq(tree[rt].po,p)){tree[rt].v+=v,tree[rt].sum+=v;return;}
if(p[k]<=tree[rt].po[k])insert(p,v,ls(rt),(k+1)%dk);
else insert(p,v,rs(rt),(k+1)%dk);
pu(rt);
if(isbad(rt))rebuild(rt,k);
}
bool in(tp a1,tp a2,tp b1,tp b2){//(a1,a2) in (b1,b2)
rep(i,0,dk-1){
if(a1[i]<b1[i]||a2[i]>b2[i])return 0;
}
return 1;
}
bool out(tp a1,tp a2,tp b1,tp b2){//(a1,a2) completely out of (b1,b2)
rep(i,0,dk-1){
if(a2[i]<b1[i]||a1[i]>b2[i])return 1;
}
return 0;
}
int qu(tp a1,tp a2,int rt){
if(rt==0||out(a1,a2,tree[rt].mi,tree[rt].mx))return 0;
if(in(tree[rt].mi,tree[rt].mx,a1,a2))return tree[rt].sum;
int res=0;
if(in(tree[rt].po,tree[rt].po,a1,a2))res+=tree[rt].v;
res+=qu(a1,a2,ls(rt))+qu(a1,a2,rs(rt));
return res;
}
[模板] K-D Tree的更多相关文章
- LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)
为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...
- 洛谷P3690 [模板] Link Cut Tree [LCT]
题目传送门 Link Cut Tree 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代 ...
- 洛谷 [P2483] [模板] k短路
人生中的第一道黑题... 其实就是k短路模板 #include <iostream> #include <cstdio> #include <cstring> #i ...
- [模板] k短路
简介 Dijkstra最短路+A*搜索. 先逆向求所有点到终点的最短路 \(dis[i]\). 定义估价函数 \(f[i] = d[i] + dis[i]\) , 其中 \(d[i]\) 表示当前起点 ...
- 【模板】Link-Cut Tree
#include<cstdio> #include<algorithm> #define N 500010 #define rg register #define ls (c[ ...
- 模板Link Cut Tree (动态树)
题目描述 给定N个点以及每个点的权值,要你处理接下来的M个操作.操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联 ...
- 洛谷.3690.[模板]Link Cut Tree(动态树)
题目链接 LCT(良心总结) #include <cstdio> #include <cctype> #include <algorithm> #define gc ...
- 第46届ICPC澳门站 K - Link-Cut Tree // 贪心 + 并查集 + DFS
原题链接:K-Link-Cut Tree_第46屆ICPC 東亞洲區域賽(澳門)(正式賽) (nowcoder.com) 题意: 要求一个边权值总和最小的环,并从小到大输出边权值(2的次幂):若不存在 ...
- Size Balanced Tree(SBT) 模板
首先是从二叉搜索树开始,一棵二叉搜索树的定义是: 1.这是一棵二叉树: 2.令x为二叉树中某个结点上表示的值,那么其左子树上所有结点的值都要不大于x,其右子树上所有结点的值都要不小于x. 由二叉搜索树 ...
- Size Balance Tree(SBT模板整理)
/* * tree[x].left 表示以 x 为节点的左儿子 * tree[x].right 表示以 x 为节点的右儿子 * tree[x].size 表示以 x 为根的节点的个数(大小) */ s ...
随机推荐
- 好吧,CSS3 3D transform变换,不过如此!——张鑫旭
一.写在前面的秋裤 早在去年的去年,我就大肆介绍了2D transform相关内容.看过海贼王的都知道,带D的家伙都不是好惹的,2D我辈尚可以应付,3D的话,呵呵,估计我等早就在千里之外被其霸气震晕了 ...
- Catalan卡特兰数入门
简介 卡特兰数是组合数学中的一种常见数列 它的前几项为: 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, ...
- C#监控指定目录的文件变化的代码
如下的资料是关于C#监控指定目录的文件变化的代码. FileSystemWatcher watcher = new FileSystemWatcher();watcher.Path = @" ...
- PHP实现开心消消乐的算法示例
本文主要介绍了关于PHP如何实现我们大家都知道的开心消消乐的算法,分享PHP教程出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 一.需求描述: 1.在一个8*8的矩阵方格中随机 ...
- Http 压测工具 wrk 基本使用
Http 压测工具 wrk 基本使用 Intro wrk 是一款现代HTTP基准测试工具,能够在单个多核CPU上运行时产生显着负载.它将多线程设计与可扩展事件通知系统(如epoll和kqueue)结合 ...
- Skywalking部署常见问题以及注意事项
Skywalking部署常见问题以及注意事项 Intro SkyWalking 创建与2015年,提供分布式追踪功能.从5.x开始,项目进化为一个完成功能的Application Performanc ...
- .net DLL版本管理
每个DLL打上版本号,方便识别维护
- c/c++ 多线程 层级锁
多线程 层级锁 当要同时操作2个对象时,就需要同时锁定这2个对象,而不是先锁定一个,然后再锁定另一个.同时锁定多个对象的方法:std::lock(对象1.锁,对象2.锁...) 但是,有的时候,并不能 ...
- 使用mybatis操作AS400数据库
先简单说一下怎么使用[jt400.jar]连接AS400上的DB2数据库. ※ jt400.jar资源,如果有安装AS400客户端的话,参考IBM官网 ※ http://www-01.ibm.com/ ...
- LeetCode算法题-Number Complement(Java实现-五种解法)
这是悦乐书的第240次更新,第253篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第107题(顺位题号是476).给定正整数,输出其补码数.补充策略是翻转其二进制表示的位 ...