一天一道算法题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 个数组对 (ci,b)(ci,b),即 (c1,b),(c2,b),...,(cm,b)(c1,b),(c2,b),...,(cm,b) ,根据前面的问题要求,分别计算出它们的答案,最后,你要给出所有答案的总和。其中,1≤i≤m1≤i≤m 。注意,数组 cici 是从 aa 数组转化而来的。下面是关于数组 cici 的定义:

  • ci1=i,
  • cij=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 。


题目解析

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

问题解析

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

解决思路

  • 对于每个数组对 (ci,b)(ci, b)(ci,b),我们可以首先将 ab 排序,这样可以方便找到满足条件 'ai<bi'`ai < bi`'ai<bi' 的最优方案。
  • 数组 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();
    }
}
相关推荐
丘山望岳18 分钟前
二叉搜索双壁——map和set
开发语言·数据结构·c++
狮子座明仔19 分钟前
DeCoRL:把推理链拆成“乐团合奏“——AAAI 2026 一篇把 RLHF 推到 32B 打 GPT-4o 的工作
人工智能·深度学习·算法
QiLinkOS20 分钟前
合肥气链科技有限公司创办与未来技术应用
c语言·数据结构·c++·人工智能·单片机·嵌入式硬件·算法
妄想出头的工业炼药师26 分钟前
追踪定位大模型
算法·开源
Solis程序员28 分钟前
TreeMap 核心原理与实战
java·数据结构·算法
Dlrb121128 分钟前
数据结构-内核链表
linux·数据结构·链表·内核链表·inline·容器宏
zzzsde37 分钟前
【Linux】线程同步和互斥(5):线程池的实现&&线程安全
linux·运维·服务器·开发语言·算法·安全
weixin_4684668537 分钟前
机器学习数据预处理新手实战指南
人工智能·python·算法·机器学习·编程·数据预处理
国科安芯1 小时前
ASM232S电气特性与TIA/EIA-232-F及ITU V.28标准符合性深度分析
单片机·嵌入式硬件·算法·安全·架构
资深流水灯工程师1 小时前
MEMS 加速度计在手表、手环及无人机上的核心应用
算法