大概就是个复杂度对的暴力做法,在你不想写二维线段树等的时候优秀的替代品。
优点:思路简单,代码好写。
他大概有两种用法(虽然差不多)。
在平面坐标系中干一些事情:
例如最常规的平面最近最远点,不管是欧几里得距离还是曼哈顿距离,本质上都是一样的。
利用不同维度的尽量平均的分割,再在询问时剪枝。
这里给出一个曼哈顿距离上的最近最远距离的版本,可供参考:
1 namespace KD { 2 int Rt, lc[N], rc[N], u[N], d[N], l[N], r[N]; 3 inline void Merge(int x, int y) { 4 u[x] = std::max(u[x], u[y]); 5 d[x] = std::min(d[x], d[y]); 6 l[x] = std::min(l[x], l[y]); 7 r[x] = std::max(r[x], r[y]); 8 } 9 inline void Up(int t) { 10 l[t] = r[t] = p[t].v[0]; 11 u[t] = d[t] = p[t].v[1]; 12 if (lc[t]) Merge(t, lc[t]); 13 if (rc[t]) Merge(t, rc[t]); 14 } 15 int Build(int l, int r, int dep) { 16 if (l >= r) { 17 if (l == r) Up(l); 18 return (l == r)? (l) : (0); 19 } 20 Mt = dep & 1; int md = (l + r) >> 1; 21 std::nth_element(p + l, p + md, p + 1 + r); 22 lc[md] = Build(l, md - 1, dep + 1); 23 rc[md] = Build(md + 1, r, dep + 1); 24 Up(md); return md; 25 } 26 inline int In_mi(int t) { 27 int re = 0; 28 re += std::max(qi.v[0] - r[t], 0); 29 re += std::max(l[t] - qi.v[0], 0); 30 re += std::max(qi.v[1] - u[t], 0); 31 re += std::max(d[t] - qi.v[1], 0); 32 return re; 33 } 34 inline int In_ma(int t) { 35 int re = 0; 36 re += std::max(std::abs(qi.v[0] - r[t]), std::abs(qi.v[0] - l[t])); 37 re += std::max(std::abs(qi.v[1] - u[t]), std::abs(qi.v[1] - d[t])); 38 return re; 39 } 40 void Query_mi(int t, int dep) { 41 if (!t) return; Mt = dep & 1; 42 if (qi != p[t]) ani = std::min(ani, Dis(qi, p[t])); 43 int dl = (lc[t])? (In_mi(lc[t])) : (INF); 44 int dr = (rc[t])? (In_mi(rc[t])) : (INF); 45 if (dl < dr) { 46 if (ani > dl) Query_mi(lc[t], dep + 1); 47 if (ani > dr) Query_mi(rc[t], dep + 1); 48 } else { 49 if (ani > dr) Query_mi(rc[t], dep + 1); 50 if (ani > dl) Query_mi(lc[t], dep + 1); 51 } 52 } 53 void Query_ma(int t, int dep) { 54 if (!t) return; Mt = dep & 1; 55 ana = std::max(ana, Dis(qi, p[t])); 56 int dl = (lc[t])? (In_ma(lc[t])) : (0); 57 int dr = (rc[t])? (In_ma(rc[t])) : (0); 58 if (dl > dr) { 59 if (ana < dl) Query_ma(lc[t], dep + 1); 60 if (ana < dr) Query_ma(rc[t], dep + 1); 61 } else { 62 if (ana < dr) Query_ma(rc[t], dep + 1); 63 if (ana < dl) Query_ma(lc[t], dep + 1); 64 } 65 } 66 }