初学kd树
一开始不会kd树的时候,感觉kd树一定很神,学了kd树发现kd树挺好写。
kd树的每个节点有一个分割超平面,我是以深度%维数作为当前这一维的分割,比较时对于当前节点就比较这一维。
附上模板代码,求平面第k近距离(kd树裸题)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<cmath> 7 using namespace std; 8 #define maxn 100020 9 #define inf 0x3f3f3f3f3f3f3fll 10 11 int now; 12 typedef long long ll; 13 struct point{ 14 int x[2]; 15 bool operator < (point a)const{ 16 return x[now] < a.x[now]; 17 } 18 }a[maxn]; 19 priority_queue <ll> heap; 20 int n,k,id; 21 ll curd; 22 23 void build(int l,int r,int dep){ 24 if ( l > r ) return; 25 now = dep % 2; 26 int mid = (l + r) >> 1; 27 nth_element(a + l,a + mid,a + r + 1); 28 build(l,mid - 1,dep + 1); 29 build(mid + 1,r,dep + 1); 30 } 31 inline ll sqr(int x){ return (ll)x * x; } 32 inline ll dis(int x1,int x2,int y1,int y2){ 33 return sqr(x1 - x2) + sqr(y1 - y2); 34 } 35 void query(point p,int l,int r,int dep){ 36 if ( l > r ) return; 37 now = dep % 2; 38 int mid = (l + r) >> 1; 39 ll tmp = dis(p.x[0],a[mid].x[0],p.x[1],a[mid].x[1]); 40 if ( mid > id ){ 41 if ( heap.size() < k ) heap.push(tmp); 42 else if ( heap.top() > tmp ){ heap.pop(); heap.push(tmp);} 43 } 44 if ( l == r ) return; 45 if ( p.x[now] > a[mid].x[now] ){ 46 query(p,mid + 1,r,dep + 1); 47 now = dep % 2; 48 if ( heap.size() < k || heap.top() >= sqr(p.x[now] - a[mid].x[now]) ) query(p,l,mid - 1,dep + 1); 49 } 50 else{ 51 query(p,l,mid - 1,dep + 1); 52 now = dep % 2; 53 if ( heap.size() < k || heap.top() >= sqr(p.x[now] - a[mid].x[now]) ) query(p,mid + 1,r,dep + 1); 54 } 55 } 56 int main(){ 57 freopen("star.in","r",stdin); 58 freopen("star.out","w",stdout); 59 scanf("%d %d",&n,&k); 60 for (int i = 1 ; i <= n ; i++){ 61 scanf("%d %d",&a[i].x[0],&a[i].x[1]); 62 } 63 build(1,n,1); 64 for (int i = 1 ; i <= n ; i++){ 65 id = i; 66 query(a[i],1,n,1); 67 } 68 printf("%lld\n",heap.top()); 69 return 0; 70 }
以后多学习kd树的应用,kd树模型可以应用的题的类型。