BZOJ 2648: SJY摆棋子

Posted You Siki

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 2648: SJY摆棋子相关的知识,希望对你有一定的参考价值。

2648: SJY摆棋子

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 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

Sample Output


1
2

HINT

 

 

kdtree可以过

 

Source

[Submit][Status][Discuss]

 

既然题目都这么友好地告诉我们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 }
View Code

@Author: YouSiki

以上是关于BZOJ 2648: SJY摆棋子的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2648 SJY摆棋子

bzoj 2648 SJY摆棋子——KDtree

BZOJ2648 SJY摆棋子

Bzoj2648 SJY摆棋子

BZOJ 2648: SJY摆棋子

bzoj 2648: SJY摆棋子