【bzoj2648】SJY摆棋子(kdtree)
题意:
二维平面上有若干个点。
现在要维护一种数据结构,支持插入一个点以及询问其余点到某个点的最小曼哈顿距离。
思路:
这是个\(kdtree\)模板题。
\(kdtree\)是一种可以高效处理\(k\)维空间信息的结构。一般我们遇到的是\(2\)维空间或者\(3\)维空间。
一般用来解决的问题为:空间最近点对、空间第\(k\)远点对、矩阵查询等问题,这些问题离线可以离线\(cdq\)解决,但是用\(kdtree\)的话可以在线处理这些问题。
一般认为一次操作期望复杂度是\(\sqrt{n}\)的,但最坏情况下复杂度为\(O(n)\)。所以我们其实可以将它看作一种玄学且比较优美的暴力~一般我们都直接定义全局变量然后大力减枝。
开局建颗树,减枝刷题数!
回到这个题,查询的话\(ans\)注意是全局变量。另外还定义了一个估价函数,含义是到达那个矩形内部的最好情况,显然这个最好情况如果都大于目前的\(ans\),我们可以不用搜索该子树。
如果类似于一个圆就可能被卡到\(O(n^2)\)
细节见代码:
/*
* Author: heyuhhh
* Created Time: 2019/11/22 14:12:30
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <iomanip>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#define Local
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e6 + 5;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n, m;
int D;
const int dim = 2;
struct Point {
int d[2], mn[2], mx[2], l, r;
int& operator [] (int x) {return d[x];}
Point(int x = 0, int y = 0) {
l = r = 0;
d[0] = x; d[1] = y;
}
}p[N >> 1];
bool operator < (Point A, Point B) {
return A[D] < B[D];
}
struct kdtree {
int rt, ans; //注意ans定义为全局变量
Point tree[N], T;
void upd(int o) {
Point ls = tree[tree[o].l], rs = tree[tree[o].r];
for(int i = 0; i < dim; i++) {
if(tree[o].l) {
tree[o].mn[i] = min(tree[o].mn[i], ls.mn[i]);
tree[o].mx[i] = max(tree[o].mx[i], ls.mx[i]);
}
if(tree[o].r) {
tree[o].mn[i] = min(tree[o].mn[i], rs.mn[i]);
tree[o].mx[i] = max(tree[o].mx[i], rs.mx[i]);
}
}
}
int build(int l, int r, int now) {
D = now;
int mid = (l + r) >> 1;
nth_element(p + l, p + mid, p + r + 1);
tree[mid] = p[mid];
for(int i = 0; i < dim; i++) {
tree[mid].mn[i] = tree[mid].mx[i] = tree[mid][i];
}
if(l < mid) tree[mid].l = build(l, mid - 1, now ^ 1);
if(r > mid) tree[mid].r = build(mid + 1, r, now ^ 1);
upd(mid);
return mid;
}
void insert(int o, int now) {
D = now;
if(T[D] < tree[o][D]) {
if(tree[o].l) insert(tree[o].l, now ^ 1);
else {
tree[o].l = ++n;
tree[n] = T;
for(int i = 0; i < dim; i++) {
tree[n].mx[i] = tree[n].mn[i] = T[i];
}
}
} else {
if(tree[o].r) insert(tree[o].r, now ^ 1);
else {
tree[o].r = ++n;
tree[n] = T;
for(int i = 0; i < dim; i++) {
tree[n].mx[i] = tree[n].mn[i] = T[i];
}
}
}
upd(o);
}
int dis(Point A, Point B) {
int res = 0;
for(int i = 0; i < dim; i++) {
res += abs(A[i] - B[i]);
}
return res;
}
int get(Point A, Point B) {//估价函数
int res = 0;
for(int i = 0; i < dim; i++) {
res += max(0, A[i] - B.mx[i]) + max(0, B.mn[i] - A[i]);
}
return res;
}
void query(int o) {
ans = min(ans, dis(tree[o], T));
int l = INF, r = INF;
if(tree[o].l) l = get(T, tree[tree[o].l]);
if(tree[o].r) r = get(T, tree[tree[o].r]);
if(l < r) {
if(l < ans) query(tree[o].l);
if(r < ans) query(tree[o].r);
} else {
if(r < ans) query(tree[o].r);
if(l < ans) query(tree[o].l);
}
}
}kd;
void run(){
n = read(), m = read();
for(int i = 1; i <= n; i++) {
int x = read(), y = read();
p[i] = Point(x, y);
}
kd.rt = kd.build(1, n, 0);
while(m--) {
int t = read(), x = read(), y = read();
kd.T = Point(x, y);
if(t == 1) {
kd.insert(kd.rt, 0);
} else {
kd.ans = INF;
kd.query(kd.rt);
printf("%d\n", kd.ans);
}
}
}
int main() {
run();
return 0;
}
【bzoj2648】SJY摆棋子(kdtree)的更多相关文章
- [BZOJ2648] SJY摆棋子 kd-tree
2648: SJY摆棋子 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 5421 Solved: 1910[Submit][Status][Disc ...
- BZOJ2648: SJY摆棋子&&2716: [Violet 3]天使玩偶
BZOJ2648: SJY摆棋子 BZOJ2716: [Violet 3]天使玩偶 BZOJ氪金无极限... 其实这两道是同一题. 附上2648的题面: Description 这天,SJY显得无聊. ...
- 【BZOJ2648】SJY摆棋子 KDtree
[BZOJ2648]SJY摆棋子 Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找 ...
- 【BZOJ2648】SJY摆棋子 [KD-tree]
SJY摆棋子 Time Limit: 20 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description 这天,SJY显得无聊.在家自己 ...
- BZOJ 2648: SJY摆棋子 kdtree
2648: SJY摆棋子 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=2648 Description 这天,SJY显得无聊.在家自己玩 ...
- luoguP4169 [Violet]天使玩偶/SJY摆棋子 K-Dtree
P4169 [Violet]天使玩偶/SJY摆棋子 链接 luogu 思路 luogu以前用CDQ一直过不去. bzoj还是卡时过去的. 今天终于用k-dtree给过了. 代码 #include &l ...
- BZOJ2648 SJY摆棋子(KD-Tree)
板子题. #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> # ...
- KDTree(Bzoj2648: SJY摆棋子)
题面 传送门 KDTree 大概就是一个分割\(k\)维空间的数据结构,二叉树 建立:每层选取一维为关键字,把中间的点拿出来,递归左右,有个\(STL\)函数nth_element可以用一下 维护:维 ...
- [bzoj2648]SJY摆棋子(带插入kd-tree)
解题关键:带插入kdtree模板题. #include<iostream> #include<cstdio> #include<cstring> #include& ...
- 【kd-tree】bzoj2648 SJY摆棋子
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define ...
随机推荐
- 面向对象~~类的成员: 私有成员,公有成员, 实例方法, 类方法, 静态方法, 属性(property), isinstance ,issubclass, 元类(type)
一 私有成员公有成员 公有成员: 在任何地方都能访问 私有成员: 只有在类的内部才能访问 类从加载时,只要遇到类中的私有成员,都会在私有成员前面加上_类名 二 实例方法 实例方法就是类的实例能够使用的 ...
- LINUX中查看、添加、删除PATH以及永久添加PATH
1.查看PATH变量 echo $PATH 会出现: 路径1:路径2:路径3 2.添加PATH变量 export PATH=$PATH:新添加的路径 用此方法添加的PATH,在关闭或者重启LINUX后 ...
- PHP的stdClass
概述 以下是百度百科对php中的 stdClass的描述: stdClass在PHP5才开始被流行.而stdClass也是zend的一个保留类.stdClass类是PHP的一个内部保留类,初始时没有成 ...
- WPF 动态列(DataGridTemplateColumn) 绑定数据 (自定义控件)
原文:WPF 动态列(DataGridTemplateColumn) 绑定数据 (自定义控件) 因为项目需要 要实现这个~ 怎么实现画红框内容部分 田字格和上面Textbox 属于一个自定义控件 大 ...
- Noip2016Day1T2 天天爱跑步
题目链接 problem solution 这是一道一个顶六个的好题!!! 说一下各档部分分怎么写吧. 先看一下\(S_i=1\)和\(T_i=1\)的部分分怎么写. 如果\(S_i=1\) 当且仅当 ...
- Python进阶小结
目录 一.异常TODO 二.深浅拷贝 2.1 拷贝 2.2 浅拷贝 2.3 深拷贝 三.数据类型内置方法 3.1 数字类型内置方法 3.1.1 整型 3.1.2 浮点型 3.2 字符串类型内置方法 3 ...
- bootstrap 输入框后面有个按钮
效果如下: 实现代码:
- PHPexcel导入数据的时候出现object解决方法
打印其他数据都是正常的,就这个是一个对象 从表格里面看不出问题 后面找到原因是表格里那个名字 李珊珊 周围有空白字符,去掉之后就能正常导入, 解决方法: 找到导入文件的那个方法 ...
- oracle学习笔记(十) 查询练习(一)
查询练习一 表创建 create table employee as select * from soctt.emp ; --记得授权 sysdba用户登录 grant select on scott ...
- WPF中Button的背景图片,实现禁止IsMouseOver时显示默认
<Button x:Name="btnPickUpNum" Click="PickUpNum_OnClick" Grid.Row="1" ...