一天一道算法题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();
    }
}
相关推荐
不喜欢学数学er2 分钟前
算法第五十二天:图论part03(第十一章)
算法·深度优先·图论
养成系小王2 分钟前
四大常用排序算法
数据结构·算法·排序算法
NAGNIP3 分钟前
一文搞懂DeepSeek LLM
算法
已读不回14319 分钟前
设计模式-策略模式
前端·算法·设计模式
CoovallyAIHub1 小时前
标注成本骤降,DINOv3炸裂发布!冻结 backbone 即拿即用,性能对标SOTA
深度学习·算法·计算机视觉
BB学长1 小时前
流固耦合|01流固耦合分类
人工智能·算法
汤永红1 小时前
week3-[分支嵌套]方阵
c++·算法·信睡奥赛
广州智造1 小时前
EPLAN教程:流体工程
开发语言·人工智能·python·算法·软件工程·软件构建
闪电麦坤951 小时前
数据结构:从前序遍历序列重建一棵二叉搜索树 (Generating from Preorder)
数据结构··二叉搜索树
闪电麦坤952 小时前
数据结构:二叉树的遍历 (Binary Tree Traversals)
数据结构·二叉树·