读题
从 n 道题中选 m 道组成题单,签到题是题单中难度最低的所有题
目标:最大化签到题的数量
解题思路
若题单中最低难度为d,则签到题数量是难度d的题数(记为a[d]),且需满足 “难度≥d 的题总数≥m”(才能选出 m 道题)。
步骤:
用数组a统计每个难度的题数(a[d]表示难度d的题有多少道)。
从最大难度n往最小难度1遍历,累加 “难度≥当前 i” 的总题数p。
当p≥m时,说明可以选 m 道题且最低难度为i,此时签到题数量为a[i],记录这些a[i]的最大值。
最终答案是 “最大的a[i]” 和 “m” 的较小值(因为若a[i]≥m,最多只能选 m 道作为签到题)。
#include<stdio.h>
#define MAXN 200010 // 题目中a_i≤n,n≤2e5,数组大小足够
int main() {
int n, m, k;
int a[MAXN] = {0}; // 初始化数组,a[d]记录难度d的题数
int p = 0; // 累计"难度≥当前i"的总题数
int ans = 0; // 记录最大的签到题数量
// 读入n和m
scanf("%d %d", &n, &m);
// 统计每个难度的题数
for (int i = 1; i <= n; i++) {
scanf("%d", &k);
a[k]++; // 难度k的题数+1
}
// 从最大难度往最小难度遍历
for (int i = n; i >= 1; i--)
{
p += a[i]; // 累加当前难度i的题数(p变为"难度≥i"的总题数)
// 若p≥m,说明能选m道题且最低难度为i,更新ans
if (p >= m)
{
// 取当前a[i]和已有ans的最大值
if (a[i] > ans) {ans = a[i];}
}
}
// 最大的a[i]不能超过m(因为最多选m道题)
if (ans > m){ans = m;}
printf("%d\n", ans);
return 0;
}

京公网安备 11010502036488号