[2019牛客多校训练第8场]Distance

链接:https://ac.nowcoder.com/acm/contest/888/D
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 524288K,其他语言1048576K

64bit IO Format: %lld

分数:2500 前期题但是貌似没想到

题目描述

Gromah and LZR have entered the fourth level. There is a blank cube with size n × m × h n\times m\times h n×m×h hanging on the wall.

Gromah soon finds a list beside the cube, there are q ​ _{}q​ q instructions in the list and each instruction is in one of the following two formats:

  1. ( 1 , x , y , z ) _{}(1,x,y,z) (1,x,y,z)​, meaning to add a tag on position ( x , y , z ) _{}(x,y,z) (x,y,z)​ in the cube
  2. ( 2 , x , y , z ) _{}(2,x,y,z) (2,x,y,z)​, meaning to determine the minimum Manhattan Distance to the given position ( x , y , z ) _{}(x,y,z) (x,y,z)​ among all tagged positions

Manhattan Distance between two positions ( x 1 , y 1 , z 1 ) , ( x 2 , y 2 , z 2 ) (x_1, y_1, z_1), (x_2, y_2, z_2) (x1,y1,z1),(x2,y2,z2) is defined as ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ + ∣ z 1 − z 2 ∣ |x_1 - x_2| + |y_1 - y_2| + |z_1 - z_2| x1x2+y1y2+z1z2.

LZR also finds a note board saying that the password of this level is the sequence made up of all results of the instructions in format 2.

Please help them get all results of the instructions in format 2.
输入描述:

The first line contains four positive integers n , m , h , q _{}n,m,h,q n,m,h,q​, denoting the sizes in three dimensions of the cube and the number of instructions.

Following q _{}q q​ lines each contains four positive integers o p , x , y , z ​ _{}op,x,y,z​ op,x,y,z, where o p = 1 _{}op=1 op=1​ means to add a tag on ( x , y , z ) _{}(x,y,z) (x,y,z)​ while o p = 2 _{}op=2 op=2​ means to make a query on ( x , y , z ) _{}(x,y,z) (x,y,z)​.
1 ≤ n × m × h , q ≤ 1 0 5 , 1 ≤ x ≤ n , 1 ≤ y ≤ m , 1 ≤ z ≤ h 1 \le n\times m\times h, q\le 10^5, 1 \le x \le n, 1 \le y \le m, 1 \le z \le h 1n×m×h,q105,1xn,1ym,1zh

It is guaranteed that the first instruction is in format 1 and that no position will be tagged more than once.

输出描述:

For each instruction in format 2, output the answer in one line.

示例1
输入

3 3 3 4
1 1 1 1
2 2 3 3
1 3 1 1
2 3 3 2

输出

5
3

For the first query, there is only one tagged position ( 1 , 1 , 1 ) _{}(1,1,1) (1,1,1)​ currently, so the answer is ∣ 1 − 2 ∣ + ∣ 1 − 3 ∣ + ∣ 1 − 3 ∣ = 5 _{}∣1−2∣+∣1−3∣+∣1−3∣=5 12+13+13=5​.
For the second query, ( 3 , 1 , 1 ) _{}(3,1,1) (3,1,1)​ is the nearest tagged position, so the answer is ∣ 3 − 3 ∣ + ∣ 1 − 3 ∣ + ∣ 1 − 2 ∣ = 3 ​ _{}∣3−3∣+∣1−3∣+∣1−2∣=3​ 33+13+12=3.

题意:
给定一个长宽高分别为n,m,h的三维空间
有两种操作,一种是往空间中放一个点,第二种是询问一个点,问空间中与这个点距离最近的点的距离。
题解:
n × m × h &lt; = 1 0 5 n\times m\times h &lt;= 10^5 n×m×h<=105这是个好事
假设我们的所有询问都在放置之后,那么我们可以放完之后做一次bfs来更新所有点的答案,但是现在查询和更新是混淆的。那么我们每次插入一个点的时候,就直接从这个点开始bfs更新能够更新的距离(跟最短路很像),然后查询的时候直接O(1)查询答案即可。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int dx[8]={1,-1,0,0,0,0},
    dy[8]={0,0,1,-1,0,0},
    dz[8]={0,0,0,0,1,-1};
struct point{
    int x,y,z;
    point(){}
    point(int _x,int _y,int _z){
        x=_x;
        y=_y;
        z=_z;
    }
};
vector<vector<vector<int> > >dis;
queue<point>q;
int n,m,h,Q;
int ans[100004];

void bfs(){
    while(!q.empty()){
        point now=q.front();q.pop();
        int nd=dis[now.x][now.y][now.z];
        for(int i=0;i<6;i++){
            point np=now;
            np.x+=dx[i];np.y+=dy[i];np.z+=dz[i];
            if(np.x<0||np.x>=n||np.y<0||np.y>=m||np.z<0||np.z>=h){
                continue;
            }
            if(dis[np.x][np.y][np.z]==-1||dis[np.x][np.y][np.z]>nd+1){
                dis[np.x][np.y][np.z]=nd+1;
                q.push(np);
            }
        }
    }
}
int main(){
    scanf("%d%d%d%d",&n,&m,&h,&Q);
    for(int i=1;i<=n;i++){
        vector<vector<int> >cc;
        for(int j=1;j<=m;j++){
            vector<int>pp;
            for(int k=1;k<=h;k++){
                pp.push_back(-1);
            }
            cc.push_back(pp);
        }
        dis.push_back(cc);
    }
    int cnt=0;
    for(int i=1;i<=Q;i++){
        int t,x,y,z;
        scanf("%d%d%d%d",&t,&x,&y,&z);
        x--;y--;z--;
        if(t==1){
            q.push(point(x,y,z));
            dis[x][y][z]=0;
            bfs();
        }
        else{
            printf("%d\n",dis[x][y][z]);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值