【BZOJ2648】【kd_tree】SJY摆棋子
Description
这天,SJY显得无聊。在家自己玩。在一个棋盘上,有N个黑色棋子。他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子。此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) 。现在给出N<=500000个初始棋子。和M<=500000个操作。对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的距离。同一个格子可能有多个棋子。
Input
第一行两个数 N M
以后M行,每行3个数 t x y
如果t=1 那么放下一个黑色棋子
如果t=2 那么放下一个白色棋子
Output
对于每个T=2 输出一个最小距离
Sample Input
2 3
1 1
2 3
2 1 2
1 3 3
2 4 2
Sample Output
1
2
HINT
kdtree可以过
【分析】
大家都知道kd_tree是什么吧,恩
就这样了..好吧,kd_tree一种空间树..看代码就知道了
1 /* 2 唐代李白 3 《江夏别宋之悌》 4 楚水清若空,遥将碧海通。人分千里外,兴在一杯中。 5 谷鸟吟晴日,江猿啸晚风。平生不下泪,于此泣无穷. 6 */ 7 #include <iostream> 8 #include <cstdio> 9 #include <algorithm> 10 #include <cstring> 11 #include <vector> 12 #include <utility> 13 #include <iomanip> 14 #include <string> 15 #include <cmath> 16 #include <queue> 17 #include <assert.h> 18 #include <map> 19 #include <ctime> 20 #include <cstdlib> 21 #include <stack> 22 #include <set> 23 #define LOCAL 24 const int INF = 0x7fffffff; 25 const int MAXN = 100000 + 10; 26 const int maxnode = 20000 * 2 + 200000 * 20; 27 const int MAXM = 50000 + 10; 28 const int MAX = 100000000; 29 using namespace std; 30 struct Node{//kd_tree 31 int d[2], l, r; 32 int Max[2], Min[2]; 33 }t[1000000 + 10],tmp; 34 35 int n,m,root,cmp_d; 36 int k1, k2, k3, Ans; 37 38 bool cmp(Node a, Node b){return (a.d[cmp_d]<b.d[cmp_d]) || ((a.d[cmp_d] == b.d[cmp_d]) && (a.d[!cmp_d] < b.d[!cmp_d]));} 39 void update(int p){ 40 if (t[p].l){ 41 //左边最大的横坐标值 42 t[p].Max[0] = max(t[p].Max[0], t[t[p].l].Max[0]); 43 t[p].Min[0] = min(t[p].Min[0], t[t[p].l].Min[0]); 44 t[p].Max[1] = max(t[p].Max[1], t[t[p].l].Max[1]); 45 t[p].Min[1] = min(t[p].Min[1], t[t[p].l].Min[1]); 46 } 47 if (t[p].r){ 48 t[p].Max[0] = max(t[p].Max[0], t[t[p].r].Max[0]); 49 t[p].Min[0] = min(t[p].Min[0], t[t[p].r].Min[0]); 50 t[p].Max[1] = max(t[p].Max[1], t[t[p].r].Max[1]); 51 t[p].Min[1] = min(t[p].Min[1], t[t[p].r].Min[1]); 52 } 53 return; 54 } 55 //d是横竖切.. 56 int build(int l, int r, int D){ 57 int mid = (l + r) / 2; 58 cmp_d = D; 59 //按照cmp的比较顺序在l到r中找到第mid大的元素 60 nth_element(t + l + 1, t + mid + 1, t + r + 1, cmp); 61 t[mid].Max[0] = t[mid].Min[0] = t[mid].d[0]; 62 t[mid].Max[1] = t[mid].Min[1] = t[mid].d[1]; 63 //递归建树 64 if (l != mid) t[mid].l = build(l, mid - 1, D ^ 1); 65 if (r != mid) t[mid].r = build(mid + 1, r, D ^ 1); 66 update(mid); 67 return mid; 68 } 69 void insert(int now){ 70 int D = 0, p = root;//D还是表示方向 71 while (1){ 72 //边下传边更新 73 t[p].Max[0] = max(t[p].Max[0], t[now].Max[0]); 74 t[p].Min[0] = min(t[p].Min[0], t[now].Min[0]); 75 t[p].Max[1] = max(t[p].Max[1], t[now].Max[1]); 76 t[p].Min[1] = min(t[p].Min[1], t[now].Min[1]); 77 //有没有点线段树的感觉.. 78 if (t[now].d[D] >= t[p].d[D]){ 79 if (t[p].r == 0){ 80 t[p].r = now; 81 return; 82 }else p = t[p].r; 83 }else{ 84 if (t[p].l == 0){ 85 t[p].l = now; 86 return; 87 }else p = t[p].l; 88 } 89 D = D ^ 1; 90 } 91 return; 92 } 93 int ABS(int x) {return x < 0? -x : x;} 94 //dist越小代表越趋近? 95 int dist(int p1, int px, int py){ 96 int dist = 0; 97 if (px < t[p1].Min[0]) dist += t[p1].Min[0] - px; 98 if (px > t[p1].Max[0]) dist += px - t[p1].Max[0]; 99 if (py < t[p1].Min[1]) dist += t[p1].Min[1] - py; 100 if (py > t[p1].Max[1]) dist += py - t[p1].Max[1]; 101 return dist; 102 } 103 void ask(int p){ 104 int dl, dr, d0; 105 //哈密顿距离 106 d0=ABS(t[p].d[0] - k2) + ABS(t[p].d[1] - k3); 107 if(d0 < Ans) Ans = d0; 108 if(t[p].l) dl = dist(t[p].l, k2, k3); else dl = 0x7f7f7f7f; 109 if(t[p].r) dr = dist(t[p].r, k2, k3); else dr = 0x7f7f7f7f; 110 //应该是一个启发式的过程。 111 if(dl < dr){ 112 if(dl < Ans) ask(t[p].l); 113 if(dr < Ans) ask(t[p].r); 114 }else{ 115 if(dr < Ans) ask(t[p].r); 116 if(dl < Ans) ask(t[p].l); 117 } 118 } 119 120 void init(){ 121 //假设0为横坐标 122 scanf("%d%d", &n, &m); 123 for (int i = 1; i <= n; i++) 124 scanf("%d%d", &t[i].d[0], &t[i].d[1]); 125 root = build(1, n, 0); 126 } 127 void work(){ 128 for (int i = 1; i <= m ;i++){ 129 scanf("%d%d%d", &k1, &k2, &k3); 130 if (k1 == 1){//黑棋 131 ++n; 132 t[n].Max[0] = t[n].Min[0] = t[n].d[0] = k2; 133 t[n].Max[1] = t[n].Min[1] = t[n].d[1] = k3; 134 insert(n); 135 }else{ 136 Ans = 0x7f7f7f7f; 137 ask(root); 138 printf("%d\n", Ans); 139 } 140 } 141 } 142 143 int main(){ 144 145 init(); 146 work(); 147 return 0; 148 }