BZOJ 2648: SJY摆棋子
Posted You Siki
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 2648: SJY摆棋子相关的知识,希望对你有一定的参考价值。
2648: SJY摆棋子
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 2968 Solved: 1011
[Submit][Status][Discuss]
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
1 1
2 3
2 1 2
1 3 3
2 4 2
Sample Output
1
2
HINT
kdtree可以过
Source
既然题目都这么友好地告诉我们KD-Tree可解了,那就没理由不写KD-Tree了,对吧。( ̄_, ̄ )
对于原本就存在的黑色棋子,那么就先读入,然后用build()建树;对于之后插入的黑色棋子,在insert()中根据KD-Tree的二叉树性质找到合适的叶子结点,插入即可。查询的时候,记得用最优性剪枝,并且合理利用估价函数,以避免TLE。
1 #include <bits/stdc++.h> 2 3 inline int next(void) { 4 int ret = 0, neg = 0, bit = getchar(); 5 while (bit < \'0\') { 6 if (bit == \'-\') 7 neg ^= true; 8 bit = getchar(); 9 } 10 while (bit >= \'0\') { 11 ret = ret*10 + bit - \'0\'; 12 bit = getchar(); 13 } 14 return neg ? -ret : ret; 15 } 16 17 const int siz = 2e6 + 7; 18 const int inf = 2e9 + 7; 19 20 struct node { 21 int pos[2]; 22 int son[2]; 23 int min[2]; 24 int max[2]; 25 }tree[siz]; 26 27 int root; 28 int cmp_k; 29 int qry_x; 30 int qry_y; 31 int answer; 32 33 inline bool cmp(node a, node b) { 34 return 35 (a.pos[cmp_k] ^ b.pos[cmp_k]) 36 ? (a.pos[cmp_k] < b.pos[cmp_k]) 37 : (a.pos[!cmp_k] < b.pos[!cmp_k]); 38 } 39 40 inline void update(int t) { 41 for (int i = 0; i < 2; ++i)if (tree[t].son[i]) 42 for (int j = 0; j < 2; ++j) { 43 if (tree[t].min[j] > tree[tree[t].son[i]].min[j]) 44 tree[t].min[j] = tree[tree[t].son[i]].min[j]; 45 if (tree[t].max[j] < tree[tree[t].son[i]].max[j]) 46 tree[t].max[j] = tree[tree[t].son[i]].max[j]; 47 } 48 } 49 50 int build(int l, int r, int k) { 51 int d = (l + r) >> 1; cmp_k = k; 52 std::nth_element( 53 tree + l + 1, 54 tree + d + 1, 55 tree + r + 1, 56 cmp); 57 if (l != d)tree[d].son[0] = build(l, d - 1, !k); 58 if (r != d)tree[d].son[1] = build(d + 1, r, !k); 59 tree[d].min[0] = tree[d].max[0] = tree[d].pos[0]; 60 tree[d].min[1] = tree[d].max[1] = tree[d].pos[1]; 61 return update(d), d; 62 } 63 64 inline void insert(int t) { 65 for (int p = root, k = 0; p != t; k = !k) { 66 for (int i = 0; i < 2; ++i) { 67 if (tree[p].min[i] > tree[t].min[i]) 68 tree[p].min[i] = tree[t].min[i]; 69 if (tree[p].max[i] < tree[t].max[i]) 70 tree[p].max[i] = tree[t].max[i]; 71 } 72 int &to = tree[p].son[tree[t].pos[k] >= tree[p].pos[k]]; 73 to = to ? to : t; p = to; 74 } 75 } 76 77 inline int dist(int t) { 78 if (!t)return inf; 79 int ret = 0; 80 if (qry_x < tree[t].min[0]) 81 ret += tree[t].min[0] - qry_x; 82 if (qry_x > tree[t].max[0]) 83 ret += qry_x - tree[t].max[0]; 84 if (qry_y < tree[t].min[1]) 85 ret += tree[t].min[1] - qry_y; 86 if (qry_y > tree[t].max[1]) 87 ret += qry_y - tree[t].max[1]; 88 return ret; 89 } 90 91 void query(int t) { 92 answer = std::min(answer, 93 std::abs(tree[t].pos[0] - qry_x) 94 + std::abs(tree[t].pos[1] - qry_y)); 95 if (dist(tree[t].son[0]) < dist(tree[t].son[1])) { 96 if (dist(tree[t].son[0]) < answer)query(tree[t].son[0]); 97 if (dist(tree[t].son[1]) < answer)query(tree[t].son[1]); 98 } else { 99 if (dist(tree[t].son[1]) < answer)query(tree[t].son[1]); 100 if (dist(tree[t].son[0]) < answer)query(tree[t].son[0]); 101 } 102 } 103 104 signed main(void) { 105 int n = next(); 106 int m = next(); 107 for (int i = 1; i <= n; ++i) { 108 tree[i].pos[0] = next(); 109 tree[i].pos[1] = next(); 110 } 111 root = build(1, n, 0); 112 for (int i = 1; i <= m; ++i) { 113 int k = next(); 114 int x = next(); 115 int y = next(); 116 if (k == 1) { 117 ++n; 118 tree[n].min[0] = tree[n].max[0] = tree[n].pos[0] = x; 119 tree[n].min[1] = tree[n].max[1] = tree[n].pos[1] = y; 120 insert(n); 121 } 122 else { 123 qry_x = x; 124 qry_y = y; 125 answer = inf; 126 query(root); 127 printf("%d\\n", answer); 128 } 129 } 130 }
@Author: YouSiki
以上是关于BZOJ 2648: SJY摆棋子的主要内容,如果未能解决你的问题,请参考以下文章