传送门

题意:

二维平面上有若干个点。

现在要维护一种数据结构,支持插入一个点以及询问其余点到某个点的最小曼哈顿距离。

思路:

这是个\(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)的更多相关文章

  1. [BZOJ2648] SJY摆棋子 kd-tree

    2648: SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 5421  Solved: 1910[Submit][Status][Disc ...

  2. BZOJ2648: SJY摆棋子&&2716: [Violet 3]天使玩偶

    BZOJ2648: SJY摆棋子 BZOJ2716: [Violet 3]天使玩偶 BZOJ氪金无极限... 其实这两道是同一题. 附上2648的题面: Description 这天,SJY显得无聊. ...

  3. 【BZOJ2648】SJY摆棋子 KDtree

    [BZOJ2648]SJY摆棋子 Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找 ...

  4. 【BZOJ2648】SJY摆棋子 [KD-tree]

    SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 这天,SJY显得无聊.在家自己 ...

  5. BZOJ 2648: SJY摆棋子 kdtree

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

  6. luoguP4169 [Violet]天使玩偶/SJY摆棋子 K-Dtree

    P4169 [Violet]天使玩偶/SJY摆棋子 链接 luogu 思路 luogu以前用CDQ一直过不去. bzoj还是卡时过去的. 今天终于用k-dtree给过了. 代码 #include &l ...

  7. BZOJ2648 SJY摆棋子(KD-Tree)

    板子题. #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> # ...

  8. KDTree(Bzoj2648: SJY摆棋子)

    题面 传送门 KDTree 大概就是一个分割\(k\)维空间的数据结构,二叉树 建立:每层选取一维为关键字,把中间的点拿出来,递归左右,有个\(STL\)函数nth_element可以用一下 维护:维 ...

  9. [bzoj2648]SJY摆棋子(带插入kd-tree)

    解题关键:带插入kdtree模板题. #include<iostream> #include<cstdio> #include<cstring> #include& ...

  10. 【kd-tree】bzoj2648 SJY摆棋子

    #include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define ...

随机推荐

  1. Notification 弹出一个通知在桌面右下角

    if (!("Notification" in window)) { //alert("This browser does not support desktop not ...

  2. 激活windows操作系统的命令行指令

    1.开始菜单中搜索命令提示符,右键管理员运行 2.为了避免激活的失败,首先卸载已经过期的密钥 输入以下命令:slmgr.vbs /upk 回车确认之后会弹出提示“已成功卸载了产品密钥” 3.下一步是将 ...

  3. 更改 undo_retention 时,Lob retention 不更改 (Doc ID 563470.1)

    Lob retention not changing when undo_retention is changed (Doc ID 563470.1) APPLIES TO: Oracle Datab ...

  4. Shell—输入输出重定向

    大多数 UNIX 系统命令从你的终端接受输入并将所产生的输出发送回​​到您的终端.一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这恰好是你的终端.同样,一个命令通常将其输出写入到标准输出,默 ...

  5. tornado的IOLoop.instance()方法和IOLoop.current()方法区别

    在使用tornado时,经常有人疑惑IOLoop.instance()方法和IOLoop.current()方法的区别是什么. IOLoop.instance() 返回一个全局 IOLoop实例. 大 ...

  6. 自写的简单MD5加密算法

    package com.srs.tools; import java.math.BigInteger; import java.security.MessageDigest; /*********** ...

  7. Druid-代码段-4-3

    所属文章:池化技术(一)Druid是如何管理数据库连接的? 本代码段对应流程4.2,防止内存泄漏的连接关闭检测: //回收长期未归还的连接(再次说明:该方法仅在removeAbandoned设置为tr ...

  8. FFT/NTT初探

    做了全家桶然后写了几道入门题. FFT.ref NTT.ref Luogu4238 [模板]多项式求逆 Link 套牛顿迭代完事.有一个细节问题是:这次运算多项式有几项就只赋几项的值,其他位置(次数大 ...

  9. 201871010113-刘兴瑞《面向对象程序设计(java)》第十周学习总结

    项目 内容 这个作业属于哪个课程 <任课教师博客主页链接> https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 <作业链接地址>htt ...

  10. AcWing 836. 合并集合

    地址  https://www.acwing.com/problem/content/838/ 一共有n个数,编号是1~n,最开始每个数各自在一个集合中. 现在要进行m个操作,操作共有两种: “M a ...