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。

 #include <bits/stdc++.h>

 inline int next(void) {
int ret = , neg = , bit = getchar();
while (bit < '') {
if (bit == '-')
neg ^= true;
bit = getchar();
}
while (bit >= '') {
ret = ret* + bit - '';
bit = getchar();
}
return neg ? -ret : ret;
} const int siz = 2e6 + ;
const int inf = 2e9 + ; struct node {
int pos[];
int son[];
int min[];
int max[];
}tree[siz]; int root;
int cmp_k;
int qry_x;
int qry_y;
int answer; inline bool cmp(node a, node b) {
return
(a.pos[cmp_k] ^ b.pos[cmp_k])
? (a.pos[cmp_k] < b.pos[cmp_k])
: (a.pos[!cmp_k] < b.pos[!cmp_k]);
} inline void update(int t) {
for (int i = ; i < ; ++i)if (tree[t].son[i])
for (int j = ; j < ; ++j) {
if (tree[t].min[j] > tree[tree[t].son[i]].min[j])
tree[t].min[j] = tree[tree[t].son[i]].min[j];
if (tree[t].max[j] < tree[tree[t].son[i]].max[j])
tree[t].max[j] = tree[tree[t].son[i]].max[j];
}
} int build(int l, int r, int k) {
int d = (l + r) >> ; cmp_k = k;
std::nth_element(
tree + l + ,
tree + d + ,
tree + r + ,
cmp);
if (l != d)tree[d].son[] = build(l, d - , !k);
if (r != d)tree[d].son[] = build(d + , r, !k);
tree[d].min[] = tree[d].max[] = tree[d].pos[];
tree[d].min[] = tree[d].max[] = tree[d].pos[];
return update(d), d;
} inline void insert(int t) {
for (int p = root, k = ; p != t; k = !k) {
for (int i = ; i < ; ++i) {
if (tree[p].min[i] > tree[t].min[i])
tree[p].min[i] = tree[t].min[i];
if (tree[p].max[i] < tree[t].max[i])
tree[p].max[i] = tree[t].max[i];
}
int &to = tree[p].son[tree[t].pos[k] >= tree[p].pos[k]];
to = to ? to : t; p = to;
}
} inline int dist(int t) {
if (!t)return inf;
int ret = ;
if (qry_x < tree[t].min[])
ret += tree[t].min[] - qry_x;
if (qry_x > tree[t].max[])
ret += qry_x - tree[t].max[];
if (qry_y < tree[t].min[])
ret += tree[t].min[] - qry_y;
if (qry_y > tree[t].max[])
ret += qry_y - tree[t].max[];
return ret;
} void query(int t) {
answer = std::min(answer,
std::abs(tree[t].pos[] - qry_x)
+ std::abs(tree[t].pos[] - qry_y));
if (dist(tree[t].son[]) < dist(tree[t].son[])) {
if (dist(tree[t].son[]) < answer)query(tree[t].son[]);
if (dist(tree[t].son[]) < answer)query(tree[t].son[]);
} else {
if (dist(tree[t].son[]) < answer)query(tree[t].son[]);
if (dist(tree[t].son[]) < answer)query(tree[t].son[]);
}
} signed main(void) {
int n = next();
int m = next();
for (int i = ; i <= n; ++i) {
tree[i].pos[] = next();
tree[i].pos[] = next();
}
root = build(, n, );
for (int i = ; i <= m; ++i) {
int k = next();
int x = next();
int y = next();
if (k == ) {
++n;
tree[n].min[] = tree[n].max[] = tree[n].pos[] = x;
tree[n].min[] = tree[n].max[] = tree[n].pos[] = y;
insert(n);
}
else {
qry_x = x;
qry_y = y;
answer = inf;
query(root);
printf("%d\n", answer);
}
}
}

@Author: YouSiki

BZOJ 2648: SJY摆棋子的更多相关文章

  1. BZOJ 2648: SJY摆棋子 kdtree

    2648: SJY摆棋子 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=2648 Description 这天,SJY显得无聊.在家自己玩 ...

  2. bzoj 2648: SJY摆棋子&&2716: [Violet 3]天使玩偶 --kdtree

    2648: SJY摆棋子&&2716: [Violet 3]天使玩偶 Time Limit: 20 Sec  Memory Limit: 128 MB Description 这天,S ...

  3. BZOJ 2648: SJY摆棋子(K-D Tree)

    Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 6051  Solved: 2113[Submit][Status][Discuss] Descript ...

  4. bzoj 2648 SJY摆棋子 kd树

    题目链接 初始的时候有一些棋子, 然后给两种操作, 一种是往上面放棋子. 另一种是给出一个棋子的位置, 问你离它最近的棋子的曼哈顿距离是多少. 写了指针版本的kd树, 感觉这个版本很好理解. #inc ...

  5. BZOJ 2648 SJY摆棋子(KD Tree)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2648 题意: 思路: KDtree模板题. 参考自http://www.cnblogs.com/ra ...

  6. bzoj 2648 SJY摆棋子——KDtree

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2648 第一道KDtree! 学习资料:https://blog.csdn.net/zhl30 ...

  7. bzoj 2648 SJY摆棋子 —— K-D树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2648 学习资料:https://blog.csdn.net/zhl30041839/arti ...

  8. BZOJ 2648 SJY摆棋子 ——KD-Tree

    [题目分析] KD-Tree第一题,其实大概就是搜索剪枝的思想,在随机数据下可以表现的非常好NlogN,但是特殊数据下会达到N^2. 精髓就在于估价函数get以及按照不同维度顺序划分的思想. [代码] ...

  9. BZOJ 2648 SJY摆棋子(KD树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2716 [题目大意] 给出一些点,同时不断插入点和询问某点离插入点最近距离 [题解] 我 ...

随机推荐

  1. 泛型中? super T和? extends T的区别

    原文出处: 并发编程网 经常发现有List<? super T>.Set<? extends T>的声明,是什么意思呢?<? super T>表示包括T在内的任何T ...

  2. 使用JavaScript打印网页指定DIV区域

    JavaScript打印函数myPrint(obj): JavaScript打印页面指定div区域原理:使用window.open()在浏览器打开一个新的页面(window), 使用 window.d ...

  3. ELK+FileBeat+Log4Net

    ELK+FileBeat+Log4Net搭建日志系统 output { elasticsearch { hosts => ["localhost:9200"] } stdou ...

  4. C#加密解密大全

    1.方法一 (不可逆加密)     public string EncryptPassword(string PasswordString,string PasswordFormat )      { ...

  5. 向jboss写入服务器日志

    实际开发中,记录日志是常用的功能,jboss默认情况下已经记录了很多运行日志,如果开发人员要手动在server.log中写入日志,可以参考下面的方法: package utils; import ja ...

  6. variable-precision SWAR算法介绍

    BITCOUNT命令是统计一个位数组中非0进制位的数量,数学上称作:”Hanmming Weight“ 目前效率最好的为variable-precision SWAR算法,可以常数时间内计算出多个字节 ...

  7. NLog日志管理工具

    Nlog是一个很不错的.NET日志记录组件,它可以将日志输出到控件台,保存到文本,也可以很方便的记录到数据库中,或者发送Emial到指定账户. 可以在官网 这里下载Nlog:http://nlog-p ...

  8. js的浅拷贝和深拷贝

    转载:http://www.jb51.net/article/91906.htm //深拷贝,并且把合并后的值放到第二个参数里 function deepCopy(p, c) { var c = c ...

  9. STM32 (战舰)

    一.战舰STM32 1.引脚描述表---有ft 兼容5V 2.原理图----有ADC,不兼容5V 3.(1)学会基本外设:GPIO输入输出,外部中断,定时器,串口. (2)学会外设接口:SPI IIC ...

  10. [转]MyBatis传入多个参数的问题 - mingyue1818

    原文  http://www.cnblogs.com/mingyue1818/p/3714162.html 一.单个参数: public List<XXBean> getXXBeanLis ...