【JAVA】两数组的元素差值小于K的情况数(Pro20210803)(二分查找 / 双指针)

【JAVA】两数组的元素差值小于K的情况数(Pro20210803)(二分查找 / 双指针)

题目

A 国与 B 国每年都会举办一场友谊赛。该友谊赛在两国之间已举办多年,比赛规则如下:
比赛中,两国各派出 N 名参赛者,各国参赛者站成一排,面对面站立。然后,两国各派出站位相连的 K 名参赛者组成代表选手,作为一组进行比拼。比拼后,两国各自的 K 名选手返回初始位置,重新派出站位相连的 K 名选手组成队伍,进行多次比赛。注意,相同选手的组合仅能比拼一次。换句话说,如果 A 国的 1、2、3 号位选手与 B 国的 1、2、3 号位选手组队进行过一次比拼,则 A 国的 1、2、3 号位选手与 B 国的 1、2、3 号位选手都不得再次组队比拼。两国以这种方式进行比拼,直到无法再进行下去。
但是,由于是友谊赛,我们希望两国派出的站位相连的 K 名选手的能力值相加后的差值绝对值小于 X。
假设友谊赛按照上述条件进行,请算出两国之间比拼的总次数。
假设在五名选手中派出站位相连的三名参加比拼(如下所示),要求比拼中两国三名队员能力值之和的差值不大于2。
A 国选手能力值: 1 1 1 4 2
B 国选手能力值: 2 1 1 5 3
如果 A 国派出 1、2、3 号位选手组成一队(以下简称为 A123 队,A 国的能力值为 3),B 国只能派出其 1、2、3 号位选手组成队伍(以下简称为 B123 队,B 国的能力值为 4)与之比拼。除了可以和 A123 队(能力值之和为 3)比拼之外,B 国的 B123 队(能力值之和为 4)还可以与 A 国的 A234 队(能力值之和为 6)进行比拼,但是不能与 A345 队(能力值之和为 7)比拼。按此规则计算总比拼次数,则次数等于五。(A123 对 B123、A234 对 B123、A234 对 B234、A345 对 B234 以及 A345 对 B345)

[限制条件]

  1. 各国参赛者数量 N 为介于 3 到 100,000 之间的整数。
  2. 参与比拼的代表选手数量 K 为介于 2 到 N 之间的整数。
  3. 各选手的能力值为介于 1 到 100,000 之间的整数。
  4. 友谊赛的能力值差值 X 为介于 0 到 1,000,000,000 之间的整数。

[输入]
首先,给定测试用例数量 T,后面接着输入 T 种测试用例。在各个测试用例的第一行,给定两国参赛者数量 N、参与比拼的选手数量 K,以及比拼要求的能力值差值 X,以空格分隔。在第二行,按站位给定从 1 到 N 号位的 A 国 N 名选手的能力值,以空格分隔。在第三行,按站位给定从 1 到 N 号位的 B 国 N 名选手的能力值,以空格分隔。

[输出]
每个测试用例输出一行。首先,输出 “#x”(x 为测试用例编号,从 1 开始),加一个空格,然后输出案例规定条件下可进行的比拼总次数。

[输入和输出示例]
(输入)
3
5 3 2
1 1 1 4 2
2 1 1 5 3
10 3 3
2 2 2 2 2 3 3 3 3 3
1 1 1 1 1 2 2 2 1 1
5 3 100
10000 10 1000 100 1
1 2 3 4 5

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

思路:

  1. 先求出A、B数组连续区间长度为K的区间和数组SUM_A、SUM_B;

  2. 便利A数组的每个元素Ai,求出在SUM_B中,[Ai - X, Ai + X] 区间内的元素个数COUNTi;

    实现方式一(二分查找):
    对数组SUM_B进行排序后二分查找,找出从左往右的第一个大于等于【Ai - X】的下标s,以及最后一个小于等于【Ai + X】的下标e,则 COUNTi = e - s + 1。(小技巧:因为SUM_B元素均为整数,所以求SUM_B中最后一个小于等于【Ai + X】的下标e,可以转化为求SUM_B中最后一个小于等于【Ai + X + 1】的下标,再减去1)

    实现方式二(双指针):
    对数组SUM_A、SUM_B排序,初始化 s = 0,e = 0;
    遍历SUM_A,while循环,若 SUM_B[s] < Ai - X 则s++(即:找出从左往右的第一个大于等于【Ai - X】的下标s);
    while循环,若 SUM_B[e] >= Ai + X 则e++;最后e–(即:找出从左往右的最后一个小于等于【Ai + X】的下标e);
    则 COUNTi = e - s + 1。

  3. 累加每个COUNT到ASW,则ASW即为所求。

代码(二分查找):

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

public class Main {
   

	static int T, N, K;
	static long X, ASW;
	static int[] ARR_A;
	static int[] ARR_B;
	static long[] SUM_A;
	static long[] SUM_B;

	public static void main(String[] args) throws Exception {
   
		System.setIn(new FileInputStream("D:\\SW\\TestCase\\sample_input_20210803.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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值