【JAVA】求固定曼哈顿距离范围内的匹配情况数(Pro20210917)(二分 / Index Tree)

【JAVA】求固定曼哈顿距离范围内的匹配情况数(Pro20210917)(二分 / Index Tree)

題目

在一个二维平面的 X 轴上有 N 个店铺,有 M 个房屋分别散落在平面的任意位置上。可送货范围 D 是固定的,所以如果店铺与房屋之间的距离小于 D,就可以送货。距离是根据店铺与房屋在 X 轴坐标上差值的绝对值和在 Y 轴坐标上差值的绝对值之和来决定。如下图所示,字母(A、B、C)表示房屋的位置,数字(1 到 4)表示店铺的位置。图中的菱形覆盖区域是到房屋 A 的距离不超过 D 的范围。观察图片能看出,可以送货到房屋 A 的店铺有 2 个,分别为 3 和 4 号店铺。

在这里插入图片描述

输入房屋和店铺位置,编写程序,计算有一个或多个店铺可以去送货的房屋个数,以及可以形成的送货对数(一个店铺与一个可以送货的房屋就组成一对)。

[限制条件]
1.店铺数量 N 为介于 1 到 100,000 之间的整数。
2.房屋数量 M 为介于 1 到 100,000 之间的整数。
3.送货距离 D 为介于 1 到 100,000,000 之间的整数。
4.所有坐标值的绝对值是不超过 100,000,000 的整数。
5.房屋和店铺不会位于同一个位置。

[输入]
在第一行,给定测试用例数量 T。后面接着给出 T 种测试用例。在每个测试用例的第一行,给定店铺数量 N、房屋数量 M、送货距离 D,用空格分隔。接下来一行,给定 N 个店铺的 X 轴坐标值,以空格分隔。接下来的 M 行,每行给定一个房屋的 X 和 Y 轴坐标值,以空格分隔。

[输出]
以标准输出按顺序输出每个测试用例的答案。每个测试用例,都先输出“#x”(不含引号,其中 x 表示测试用例编号,从 1 开始),加上一个空格,然后输出有一个或多个店铺可以去送货的房屋数量,以及可以形成的送货对数。输出的数字以空格分隔。

[输入和输出示例]
(输入)
3
4 3 3
-4 4 1 0
0 2
-3 -1
3 -3
1 1 1
1
2 0
1 1 1
1
2 1

(输出)
#1 2 3
#2 1 1
#3 0 0

思路

对于每一个房子,求出可以到达的店铺数量,然后求和即可。
坐标为(x, y) 的房子,移动到X轴耗费的距离为d,当D >= d时,才有可能有店铺可以抵达房子,且此时,在X轴上,[x - (D - d), x + (D - d)]范围内的店铺个数,即为可以到达这个房子的店铺数;
那么,店铺坐标排序后,求出这个区间范围内的最左侧的店铺下标s(即:店铺坐标 >= x - (D - d)的最左侧的店铺下标),和最右侧的店铺下标e(即:店铺坐标 <= x + (D - d)的最右侧的店铺下标),则范围内的店铺个数 = e - s + 1;
综上,可以使用二分求s、e,也可以视为区间内求Count(区间求和)使用Index Tree。

代码(二分)

import java.io.*;
import java.util.*;

public class Main {
   

	static int T, N, M, D, SHOP[], HOUSE[][];
	static long COUNT, CASES;

	public static void main(String[] args) throws Exception {
   
		System.setIn(new FileInputStream("D:\\SW\\TestCase\\sample_input_20210917.txt"));
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());

		T = Integer.parseInt(st.nextToken());
		for (int t = 1; t <= T; t++) {
   
			st = new StringTokenizer(br.readLine());
			N = Integer.parseInt(st.nextToken());
			M = Integer.parseInt(st.nextToken());
			D = Integer.parseInt(st.nextToken());

			SHOP = new int[N + 2]
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值