题目链接

Distance

题意

1<=nmh,q<=1e5

q个操作

  • 1 x y z往坐标里加入一个点
  • 2 x y z查询距离该点最近的点的距离(曼哈顿距离)

题解

做法一

将要插入的点保存在一个队列中,当队列中的点数达到一个阈值就把队列中所有点取出,暴力的bfs一次把答案记录在\(dis[getid(x,y,z)]\)中表示距离点\((x,y,z)\)最近的点的距离,查询的时候就取暴力的计算查询点和队列中每个点的距离,再和已经插入的点也就是dis数组取最小值,当阈值取\(\sqrt{nmh}\)时复杂度为\(O(\frac{qnmh}E + qE) = O(nmh + q\sqrt{nmh})\)

做法二

将距离公式\(|x_0-x_i| + |y_0-y_i| + |z_0-z_i|\)的绝对值拆开有八种情况\(\pm(x_0-x_i) \pm (y_0-y_i) \pm (z_0-z_i)\)

这八种情况的最大值就是真正的距离,我们将插入的点分成\((\pm x, \pm y, \pm z)\)八种情况分别插入八个树状数组,树状数组维护\(x_i <= x, y_i <= y, z_i <= z的x+y+z\)的最大值,目的是为了把求最近点的距离转换成求\((x+y+z-x_i-y_i-z_i)\)的最小值,查询的时候对八个树状数组答案取min就行了

代码

做法一

#include <bits/stdc++.h>
using namespace std;
typedef long long ll; const int mx = 1e5+5;
const int mod = 998244353;
const int INF = 0x3f3f3f3f;
const int dir[6][3] = {{0,0,1}, {0,0,-1}, {0,1,0}, {0,-1,0}, {1,0,0}, {-1,0,0}};
int dis[mx];
int n, m, h, q;
struct node {
int x, y, z, step;
}; vector <node> v;
queue <node> Q; int getid(int x, int y, int z) {
return (x-1)*m*h + (y-1)*h + z;
} int getdis(int x, int y, int z, int a, int b, int c) {
return abs(x-a) + abs(y-b) + abs(z-c);
} int main() {
for (int i = 0; i < mx; i++) dis[i] = INF; scanf("%d%d%d%d", &n, &m, &h, &q);
int sq = sqrt(n*m*h) ;
while (q--) {
int op, x, y, z;
scanf("%d%d%d%d", &op, &x, &y, &z);
if (op == 1) {
v.push_back({x, y, z, 0});
if (v.size() == sq) {
for (int i = 0; i < v.size(); i++) {
Q.push(v[i]);
dis[getid(v[i].x, v[i].y, v[i].z)] = 0;
}
v.clear();
while (!Q.empty()) {
node now = Q.front();
node next;
Q.pop();
for (int i = 0; i < 6; i++) {
next.x = now.x + dir[i][0];
next.y = now.y + dir[i][1];
next.z = now.z + dir[i][2];
if (next.x < 1 || next.x > n || next.y < 1 || next.y > m || next.z < 1 || next.z > h) continue;
next.step = now.step + 1;
if (next.step < dis[getid(next.x, next.y, next.z)]) {
dis[getid(next.x, next.y, next.z)] = next.step;
Q.push(next);
}
}
}
}
} else {
int ans = dis[getid(x, y, z)];
for (int i = 0; i < v.size(); i++) {
ans = min(ans, getdis(x, y, z, v[i].x, v[i].y, v[i].z));
}
printf("%d\n", ans);
}
}
return 0;
}

做法二

#include <bits/stdc++.h>
using namespace std;
typedef long long ll; const int mx = 8e5+5;
const int mod = 998244353;
const int INF = 0x3f3f3f3f;
const int dir[8][3] = {{1,1,1}, {1,1,-1}, {1,-1,1}, {1,-1,-1}, {-1,1,1}, {-1,1,-1}, {-1,-1,1}, {-1,-1,-1}};
int dis[mx];
int n, m, h, q; int getid(int x, int y, int z) {
return (x-1)*m*h + (y-1)*h + z;
} struct Bit {
int a[mx];
int lowbit(int x) {
return x & -x;
}
void update(int x, int y, int z) {
if (x < 0) x += n;
if (y < 0) y += m;
if (z < 0) z += h;
for (int i = x; i <= n; i+=lowbit(i))
for (int j = y; j <= m; j+=lowbit(j))
for (int k = z; k <= h; k+=lowbit(k))
a[getid(i,j,k)] = max(a[getid(i,j,k)], x+y+z);
} int query(int x, int y, int z) {
if (x < 0) x += n;
if (y < 0) y += m;
if (z < 0) z += h;
int ans = 0;
for (int i = x; i > 0; i-=lowbit(i))
for (int j = y; j > 0; j-=lowbit(j))
for (int k = z; k > 0; k-=lowbit(k))
ans = max(a[getid(i,j,k)], ans);
if (ans == 0) return INF;
else return x+y+z-ans;
}
}bit[8]; int main() {
scanf("%d%d%d%d", &n, &m, &h, &q);
n++; m++; h++;
while (q--) {
int op, x, y, z;
scanf("%d%d%d%d", &op, &x, &y, &z);
if (op == 1) {
for (int i = 0; i < 8; i++) {
bit[i].update(x*dir[i][0], y*dir[i][1], z*dir[i][2]);
}
} else {
int ans = INF;
for (int i = 0; i < 8; i++) ans = min(ans, bit[i].query(x*dir[i][0], y*dir[i][1], z*dir[i][2]));
printf("%d\n", ans);
}
}
return 0;
}

D-Distance_2019牛客暑期多校训练营(第八场)的更多相关文章

  1. 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)

    题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9:  对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可.     后者mod=1e9,5才 ...

  2. 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)

    链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ...

  3. 2019牛客暑期多校训练营(第一场) B Integration (数学)

    链接:https://ac.nowcoder.com/acm/contest/881/B 来源:牛客网 Integration 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 5242 ...

  4. 2019牛客暑期多校训练营(第一场) A Equivalent Prefixes ( st 表 + 二分+分治)

    链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Equivalent Prefixes 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/ ...

  5. 2019牛客暑期多校训练营(第二场)F.Partition problem

    链接:https://ac.nowcoder.com/acm/contest/882/F来源:牛客网 Given 2N people, you need to assign each of them ...

  6. 2019牛客暑期多校训练营(第一场)A Equivalent Prefixes(单调栈/二分+分治)

    链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 Two arrays u and v each with m distinct elements ...

  7. [状态压缩,折半搜索] 2019牛客暑期多校训练营(第九场)Knapsack Cryptosystem

    链接:https://ac.nowcoder.com/acm/contest/889/D来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语言52428 ...

  8. 2019牛客暑期多校训练营(第二场)J-Subarray(思维)

    >传送门< 前言 这题我前前后后看了三遍,每次都是把网上相关的博客和通过代码认真看了再思考,然并卵,最后终于第三遍也就是现在终于看懂了,其实懂了之后发现其实没有那么难,但是的的确确需要思维 ...

  9. J-Subarray_2019牛客暑期多校训练营(第二场)

    题意 有一个只由1,-1组成的数组,给出所有连续的1所在位置,求满足1的个数大于-1的个数的子区间的数量 题解 参考博客:https://www.cnblogs.com/Yinku/p/1122149 ...

  10. 2019牛客暑期多校训练营(第一场)-A (单调栈)

    题目链接:https://ac.nowcoder.com/acm/contest/881/A 题意:给定两个长度均为n的数组a和b,求最大的p使得(a1,ap)和(b1,bp)等价,等价的定义为其任意 ...

随机推荐

  1. HPU暑期集训积分赛2

    A. 再战斐波那契 单点时限: 1.0 sec 内存限制: 512 MB 小z 学会了斐波那契和 gcd 后,老师又给他出了个难题,求第N个和第M个斐波那契数的最大公约数,这可难倒了小z ,不过在小z ...

  2. 用ECharts绘制Prometheus图表,实现类似Grafana的自定义Dashboard

      大家一般都是用Grafana自定义Dashboard来监控Prometheus数据的,作者这次尝试用ECharts来绘制Prometheus数据图表,一方面可以减少依赖,另一方面可以将监控界面灵活 ...

  3. 【Android】Fresco 初次使用遇到的坑

    初次使用开源框架 Fresco,结果遇到了坑,被虐了半下午--暂且记下. 下面的错误 android.view.InflateException: Binary XML file line #** 报 ...

  4. MyBatis框架之关联查询

    概述:关联查询主要在<resultMap>元素中,用<association>配置一对一.用<collection> 配置一对多 一.一对一查询       1.使 ...

  5. JDK的命令行工具系列 (二) javap、jinfo、jmap

    javap: 反编译工具, 可用来查看java编译器生成的字节码 参数摘要: -help 帮助 -l 输出行和变量的表 -public 只输出public方法和域 -protected 只输出publ ...

  6. 修改 jupyter notebook的默认文件夹位置

    安装好Anaconda 3以后,就可以使用Jupyter notebook了,但是我们打开Jupyter notebook后,发现界面是一个默认的目录,这个目录在哪里?如果想把自己写的程序文件保存在自 ...

  7. 02.Mybatis的动态代理方式实现增删改查

    动态代理的方式实现增删改查: 通过约定的方式定位sql语句 约定 > 配置文件 > 硬编码 约定的目标是省略掉通过硬编码的方式定位sql的代码,通过接口直接定位出sql语句,以下代码为通过 ...

  8. python开发基础--思维导图

    开始学习python,相当于零基础 非自学,自学的痛苦不想体会和尝试,毕竟不会很友好,知乎上看到很多说自学的好处啊噼里啪啦的.嗯,说的很对,但是我偏不听,略略略.锻炼我的自学能力,这还需要锻炼吗,百度 ...

  9. mybatis学习笔记(二)

    三种查询方式,由<resultType 属性控制> 第一种 selectList() 返回值为LIst List<People> selectList = session.se ...

  10. java并发编程(二十)----(JUC集合)CopyOnWriteArrayList介绍

    这一节开始我们正式来介绍JUC集合类.我们按照List.Set.Map.Queue的顺序来进行介绍.这一节我们来看一下CopyOnWriteArrayList. CopyOnWriteArrayLis ...