【JAVA】每类各选一个后求最大最小值差值的最小值(Pro20210802)(优先级队列 / IndexTree
题目:
Lin 打算在自己住的村子里建 N 个不同的便利设施。每个便利设施有 K 种建造方法,设施的便利性因建造方法而异。因此,Lin 尝试从 K 种方法中各选择一种来建造这 N 个便利设施。
当 N 个便利设施中便利性最高和最低的差值越小,便利设施越便于使用。Lin 希望算出最小的差值。
假设便利设施数量 N 为 3,各设施的建造方法数量 K 为 4(如上 [图] 中所示)。如果便利设施 ① 和 ③ 的建成便利性为 1,设施 ② 的便利性为 5,那么上文所述的便利性差值便为 4。如果便利设施 ① 建成便利性为 15,设施 ② 便利性为 17,设施 ③ 便利性为 18,则差值为 3,这是差值最小的情况。
请帮助 Lin 算出上述的最小差值。
[限制条件]
- 便利设施数量 N 和建造方法数量 K 均为介于 2 到 100,000 之间的整数。
- N * K 不得超过 1,000,000。
- 各设施的便利性值为介于 1 到 1,000,000,000 之间的整数。
- 同一便利设施的建造方法(便利性值)不会重复。
[输入]
首先,给定测试用例数量 T,后面接着输入 T 种测试用例。在每个测试用例的第一行,给定便利设施类型数量 N 和建造方式数量 K,以空格分隔。接下来的 N 行,每行以升序给定 K 个便利性数值,以空格分隔。
[输出]
每个测试用例输出一行。首先,输出 “#x”(x 为测试用例编号,从 1 开始),加一个空格,然后输出文中提到的最小差值。
[输入和输出示例]
(输入)
3
3 4
1 10 15 24
5 8 17 20
1 6 12 18
3 5
1 6 12 26 35
3 9 28 33 35
10 25 29 30 31
3 5
1 20 37 46 1000000000
1 10 30 59 999999992
10 20 28 41 1000000000
(输出)
#1 3
#2 3
#3 8
思路:
暴力求解的话,从最左侧开始,需要计算每一种可能性。
但对于 ASW = MAX - MIN 来说,想要ASW 更小,只有两种操作,即:MAX减小,或MIN增大。
从最左侧开始的话,MAX不可能再减小了,就只能MIN增大。
对于每一行来说,已经是升序的了,那就是对于MIN所在的行,取下一个,再在每行所选的元素中取最大值和最小值。
代码(优先级队列):
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
public class Main {
static int T, N, K, ASW;
static int[][] DATA; // 原始数据
public static void main(String[] args) throws Exception {
System.setIn(new FileInputStream("D:\\SW\\TestCase\\sample_input_20210802.txt"));
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(bf.readLine());
T = Integer.parseInt(st.nextToken());
for (int testcase = 1; testcase <= T; testcase++) {
st = new StringTokenizer(bf.readLine());
N = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
DATA = new int[N][K];
ASW = Integer.MAX_VALUE;
// 读取数据
for (int row