一天一道算法题day02

这是问题的简单版。在这个版本中,唯一的不同仅仅在 m=1m=1 。

现在,给定两个数组 a1,a2,...,ana1​,a2​,...,an​ 和 b1,b2,...,bnb1​,b2​,...,bn​ 。在进行操作前,你可以按照你的想法对这个数组进行重新排序。之后,在每一轮操作中,若数组非空,你将会进行以下两个子操作:

  • 从 aa 数组中选择任意一个元素,删除它(剩余的所有元素将按照原来的相对顺序转移到一个新的 aa 数组),
  • 从 bb 数组中选择任意一个元素,删除它(剩余的所有元素将按照原来的相对顺序转移到一个新的 bb 数组)。

设 kk 为两个数组的最终长度。现在,你需要找到最小的操作次数,使得对于所有的 1≤i≤k1≤i≤k ,都有 ai<biai​<bi​ 。

由于这个问题太简单了,所以,这个问题的作者准备改进题目,让它变得更有挑战性。现在,基于前面的问题,我们再给定一个正整数 mm 。对于 mm 个数组对 (c[i],b)(c[i],b),即 (c[1],b),(c[2],b),...,(c[m],b)(c[1],b),(c[2],b),...,(c[m],b) ,根据前面的问题要求,分别计算出它们的答案,最后,你要给出所有答案的总和。其中,1≤i≤m1≤i≤m 。注意,数组 c[i]c[i] 是从 aa 数组转化而来的。下面是关于数组 c[i]c[i] 的定义:

  • c[i]1=i,
  • c[i]j=aj ,其中 2≤j≤n。

输入

第一行包含一个整数 t ,表示测试样例的数量。

对于每个测试样例,第一行包含两个整数 n,m,表示数组 a,b的大小,以及元素 a1值的上限。

第二行包含 n−1 个整数 a2,...,an 。

第三行包含 n 个整数 b1,b2,...,bn 。

输出

对于每个测试样例,输出所有数组对 (ci,b)的最小操作数的总和。

样例输入

4 2 1 1 3 2 4 1 5 1 5 3 8 3 3 8 1 4 3 3 2 2 1 1 1 1 1 1 3 3 3 3 9 1 9 2 8 3 7 4 6 5 1 2 3 2 1 4 5 6 5

样例输出

0 1 4 4

提示

数据范围

对于 100%100% 的数据,保证:

1≤t≤10^4, 2≤n≤10^5, m=1, 1≤ai≤109, 1≤bi≤109。

保证所有的测试样例 n 的总和不超过 10^5 。


题目解析

这道题目要求我们找到每个数组对 (c[i],b)的最小操作次数,并最终输出这些操作次数的总和。题目通过对数组 ab 进行特定操作,要求确保 **'a[i]<b[i]'**在每一轮操作后保持成立。

问题解析

  • 给定两个数组 ab,需要从两个数组中删除元素,并保证在**每轮操作后 a[i] < b[i]**对每个 i 成立。
  • 操作次数就是每次删除的次数,最后我们要计算每个测试样例的总操作次数
  • 特别地,数组 c[i] 是从 a 数组转化而来的,其中 c[i][1] = i ,而 c[i][j] = a[j](对于 2≤j≤n

解决思路

  • 对于每个数组对 (c[i],b)(c[i], b)(c[i],b),我们可以首先将 ab 排序,这样可以方便找到满足条件 'a[i]<b[i]'`a[i] < b[i]`'a[i]<b[i]' 的最优方案。
  • 数组 a 可以重新排序,找到最小的操作次数(最少删除元素的次数)使得对每个 ia[i] < b[i] 成立。
  • 对于数组对的数量 m,我们需要对每一个 c[i] 数组分别计算操作数,然后将结果相加。

代码实现

java 复制代码
import java.util.Arrays;
import java.util.Scanner;

public class MinOperations {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int t = scanner.nextInt();  // 测试样例的数量

        while (t-- > 0) {
            int n = scanner.nextInt();  // 数组大小 n
            int m = scanner.nextInt();  // m 个数组对

            int[] a = new int[n - 1];   // 读取 a 数组(去掉 a1)
            for (int i = 0; i < n - 1; i++) {
                a[i] = scanner.nextInt();
            }

            int[] b = new int[n];   // 读取 b 数组
            for (int i = 0; i < n; i++) {
                b[i] = scanner.nextInt();
            }

            int totalOperations = 0;   // 操作次数的总和

            for (int i = 1; i <= m; i++) {
                // 创建 c[i] 数组,第一个元素是 i,接下来的元素是 a 数组
                int[] c = new int[n];
                c[0] = i;  // 第一个元素为 i
                for (int j = 1; j < n; j++) {
                    c[j] = a[j - 1];
                }

                // 对 c 和 b 数组进行排序
                Arrays.sort(c);
                Arrays.sort(b);

                // 计算最小的操作次数:使得 c[i] < b[i] 对于所有 i 成立
                int operations = 0;
                int bIndex = 0;
                for (int cIndex = 0; cIndex < n; cIndex++) {
                    while (bIndex < n && c[cIndex] >= b[bIndex]) {
                        bIndex++;  // 如果 b 数组中的数不满足条件,跳过
                    }
                    if (bIndex < n) {
                        bIndex++;  // 匹配一个,继续下一个
                    } else {
                        operations++;  // 如果不匹配,增加操作数
                    }
                }

                totalOperations += operations;  // 累计操作次数
            }

            System.out.println(totalOperations);  // 输出所有数组对的操作次数总和
        }

        scanner.close();
    }
}
相关推荐
pianmian113 分钟前
python数据结构基础(7)
数据结构·算法
好奇龙猫2 小时前
【学习AI-相关路程-mnist手写数字分类-win-硬件:windows-自我学习AI-实验步骤-全连接神经网络(BPnetwork)-操作流程(3) 】
人工智能·算法
sp_fyf_20243 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-01
人工智能·深度学习·神经网络·算法·机器学习·语言模型·数据挖掘
ChoSeitaku3 小时前
链表交集相关算法题|AB链表公共元素生成链表C|AB链表交集存放于A|连续子序列|相交链表求交点位置(C)
数据结构·考研·链表
偷心编程3 小时前
双向链表专题
数据结构
香菜大丸3 小时前
链表的归并排序
数据结构·算法·链表
jrrz08283 小时前
LeetCode 热题100(七)【链表】(1)
数据结构·c++·算法·leetcode·链表
oliveira-time3 小时前
golang学习2
算法
@小博的博客4 小时前
C++初阶学习第十弹——深入讲解vector的迭代器失效
数据结构·c++·学习
南宫生4 小时前
贪心算法习题其四【力扣】【算法学习day.21】
学习·算法·leetcode·链表·贪心算法