KD树学习小结

学习资料在这里

对于k维KDTree,实际时间复杂度为O(N*N^(1-1/k))

build实现类似spaly,不断选一维从中间划分,可以循环选取维度,也可以rand % k

求最近点的query,重点在于其中的估价函数

求区间和的query,则和线段树类似

例题:

1)模板题

bzoj 2648求最近点

  1 /*为了维持树的平衡,可以一开始把所有点都读进来build
  2 然后打flag标记该点是否被激活*/
  3 #include <bits/stdc++.h>
  4 
  5 using namespace std;
  6 
  7 const int N = 5e5 + 5;
  8 
  9 const int inf = 1 << 30;
 10 
 11 int n, m;
 12 
 13 int ql, qr, ans, tot, nowD;
 14 //nowD = rand() & 1 ?
 15 struct Node {
 16     int d[2];
 17 
 18     bool operator < (const Node &a) const {
 19         if (d[nowD] == a.d[nowD]) return d[!nowD] < a.d[!nowD];
 20         return d[nowD] < a.d[nowD];
 21     }
 22 }pot[N];
 23 
 24 struct node {
 25     int min[2], max[2], d[2];
 26     node *c[2];
 27 
 28     node() {
 29         min[0] = min[1] = max[0] = max[1] = d[0] = d[1] = 0;
 30         c[0] = c[1] = NULL;
 31     }
 32 
 33     node(int x, int y);
 34 
 35     void update();
 36 
 37     
 38 }t[N], Null, *root;
 39 
 40 node::node(int x, int y) {
 41     min[0] = max[0] = d[0] = x;
 42     min[1] = max[1] = d[1] = y;
 43     c[0] = c[1] = &Null;
 44 }
 45 
 46 inline void node::update() {
 47     if (c[0] != &Null) {
 48         if (c[0] -> max[0] > max[0]) max[0] = c[0] -> max[0];
 49         if (c[0] -> max[1] > max[1]) max[1] = c[0] -> max[1];
 50         if (c[0] -> min[0] < min[0]) min[0] = c[0] -> min[0];
 51         if (c[0] -> min[1] < min[1]) min[1] = c[0] -> min[1];
 52     }
 53     if (c[1] != &Null) {
 54         if (c[1] -> max[0] > max[0]) max[0] = c[1] -> max[0];
 55         if (c[1] -> max[1] > max[1]) max[1] = c[1] -> max[1];
 56         if (c[1] -> min[0] < min[0]) min[0] = c[1] -> min[0];
 57         if (c[1] -> min[1] < min[1]) min[1] = c[1] -> min[1];
 58     }
 59 }
 60 
 61 inline void build(node *&o, int l, int r, int D) {
 62     int mid = l + r >> 1;
 63     nowD = D;
 64     nth_element(pot + l, pot + mid, pot + r + 1);
 65     o = new node(pot[mid].d[0], pot[mid].d[1]);
 66 
 67     if (l != mid) build(o -> c[0], l, mid - 1, !D);
 68     if (r != mid) build(o -> c[1], mid + 1, r, !D);
 69     o -> update();
 70 }
 71 
 72 inline void insert(node *o) {
 73     node *p = root;
 74     int D = 0;
 75     while (1) {
 76         if (o -> max[0] > p -> max[0]) p -> max[0] = o -> max[0];
 77         if (o -> max[1] > p -> max[1]) p -> max[1] = o -> max[1];
 78         if (o -> min[0] < p -> min[0]) p -> min[0] = o -> min[0];
 79         if (o -> min[1] < p -> min[1]) p -> min[1] = o -> min[1];
 80 
 81         if (o -> d[D] >= p -> d[D]) {
 82             if (p -> c[1] == &Null) {
 83                 p -> c[1] = o;
 84                 return;
 85             } else p = p -> c[1];
 86         } else {
 87             if (p -> c[0] == &Null) {
 88                 p -> c[0] = o;
 89                 return;
 90             } else p = p -> c[0];
 91         }
 92         D ^= 1;
 93     } 
 94 }
 95 
 96 inline int dist(node *o) {
 97     int dis = 0;
 98     if (ql < o -> min[0]) dis += o -> min[0] - ql;
 99     if (ql > o -> max[0]) dis += ql - o -> max[0];
100     if (qr < o -> min[1]) dis += o -> min[1] - qr;
101     if (qr > o -> max[1]) dis += qr - o -> max[1];
102     return dis; 
103 }
104 
105 inline void query(node *o) {
106     int dl, dr, d0;
107     d0 = abs(o -> d[0] - ql) + abs(o -> d[1] - qr);
108     if (d0 < ans) ans = d0;
109     if (o -> c[0] != &Null) dl = dist(o -> c[0]);
110     else dl = inf;
111     if (o -> c[1] != &Null) dr = dist(o -> c[1]);
112     else dr = inf;
113 
114     if (dl < dr) {
115         if (dl < ans) query(o -> c[0]);
116         if (dr < ans) query(o -> c[1]);
117     } else {
118         if (dr < ans) query(o -> c[1]);
119         if (dl < ans) query(o -> c[0]);
120     }
121 }
122 
123 int main() {
124     ios::sync_with_stdio(false);
125     cin >> n >> m;
126     for (int i = 1; i <= n; i ++)
127         cin >> pot[i].d[0] >> pot[i].d[1];
128     build(root, 1, n, 0);
129     
130     for (int x, y, z; m --; ) {
131         cin >> x >> y >> z;
132         if (x == 1) {
133             t[tot].max[0] = t[tot].min[0] = t[tot].d[0] = y;
134             t[tot].max[1] = t[tot].min[1] = t[tot].d[1] = z;
135             t[tot].c[0] = t[tot].c[1] = &Null;
136             insert(&t[tot ++]);
137         } else {
138             ans = inf, ql = y, qr = z;
139             query(root), printf("%d\n", ans);
140         }
141     }
142     return 0;
143 }
View Code

这题卡常数,可以不加快读,但是建议使用inline和指针

bzoj 4066 二维平面,单点修改,区间查询

猜你喜欢

转载自www.cnblogs.com/ytytzzz/p/9625618.html