洛谷 P16460 [UOI 2026] Minimum Deletion 题解

题目传送门

注意,时间限制 300ms,不要超时了。

题目解析

  • 第一步:读入。

  • 第二步:看看最小的未出现的非负整数有没有超过 k k k,如果没有,输出 0 0 0,结束程序;如果有,继续。

  • 第三步:输出数组中小于等于 k k k 的数中出现次数最少的数的出现次数。

直接模拟即可。

代码历程

1版
#include <iostream>
#include <cstdio> // scanf 和 printf 要用
#include <climits> // INT_MAX 要用
using namespace std;
int n, k, a[1000], t = INT_MAX, b[10], l = 10; // t 表示答案,初始要设为极大值,用于与其他数取最小值。显然,出现次数最多的数的出现次数不会大于 INT_MAX(2147483647)。
// 数组 b 用来储存数组 a 中每个数字出现的次数。
// l 表示查找到后数字的下标,初始设为 10,一个特殊数字,用来标记有没有在循环中查找到小于等于 k 的非负整数。
int main() {
    scanf("%d%d", &n, &k);
    for (int i = 0; i < n; i++) scanf("%d", &a[i]), b[a[i]]++;
    for (int i = 0; i <= k; i++) if (!b[i]) { // 如果找到没有超过 k 的未出现的非负整数,就退出(这个数一定是最小的)。
        l = i;
        break;
    }
    if (l < 10) { // 如果有查找到,直接输出 0。
        printf("0\n");
        return 0;
    }
    for (int i = 0; i <= k; i++) t = min(t, b[i]); // 否则看看删除那个数用的次数最少,就是答案。
    printf("%d\n", t);
    return 0;
}
2版

发现可以优化哦。

#include <iostream>
#include <cstdio>
#include <climits>
using namespace std;
int n, k, a[1000], t = INT_MAX, b[10];
int main() {
    scanf("%d%d", &n, &k);
    for (int i = 0; i < n; i++) scanf("%d", &a[i]), b[a[i]]++;
    for (int i = 0; i <= k; i++) t = min(t, b[i]);
    printf("%d\n", t);
    return 0;
}

这么说来,其实就是看看数组 b b b b 0 , b 1 , b 2 , . . . , b k b_0,b_1,b_2,...,b_k b0,b1,b2,...,bk 中的最小值。

数组 b b b b 0 , b 1 , b 2 , . . . , b k b_0,b_1,b_2,...,b_k b0,b1,b2,...,bk 若有 0 0 0,输出是 0 0 0,符合要求;若没有 0 0 0,则输出 b 0 , b 1 , b 2 , . . . , b k b_0,b_1,b_2,...,b_k b0,b1,b2,...,bk 中的最小值,也就是最少删除数字的次数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值