您的位置:首页 > 汽车 > 时评 > 编程scratch_360建筑网简历怎么改名_生成关键词的软件免费_购物网站如何推广

编程scratch_360建筑网简历怎么改名_生成关键词的软件免费_购物网站如何推广

2025/4/27 11:22:27 来源:https://blog.csdn.net/2301_81170529/article/details/147523641  浏览:    关键词:编程scratch_360建筑网简历怎么改名_生成关键词的软件免费_购物网站如何推广
编程scratch_360建筑网简历怎么改名_生成关键词的软件免费_购物网站如何推广

题目传送门牛客网竞赛题目

一、题目描述

给定n道题目,每道题难度为aᵢ。要从中选出m道题组成比赛,使得难度最低的题目(签到题)数量尽可能多。求签到题的最大可能数量。

输入

  • 第一行两个整数n,m(1≤m≤n≤2×10⁵)
  • 第二行n个整数表示题目难度aᵢ(1≤aᵢ≤n)

示例1
输入:

5 3
1 2 2 2 3

输出:

3

二、题目分析

我们需要从n道题中选m道,使得难度最低的题目尽可能多。关键在于找出m个数的窗口,然后把最低的一个数的数量找出最大值,借助后缀和数组s实现

三、解题思路

  1. 统计每个难度出现的次数
  2. map按照键值从小到大,这道题刚刚好满足我们要的
  3. 从最小难度开始检查:如果比当前难度大的题目总数+当前难度题目数≥m,则当前难度可以作为最低难度

四、算法讲解

  1. 统计各难度出现频率(使用map自动排序)
  2. 预处理后缀和数组s[i]表示难度≥vec[i]的题目总数
  3. 对于每个难度,检查能否作为最低难度:
    • 若能,则最大数量为min(该难度题目数,m)
    • 否则终止检查(后续难度更大不可能更优,因为后缀和的是数量)

五、代码实现

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 +10;
map<int, int> mp; // 统计各难度出现次数(自动按难度排序)
int n, m;
int s[N]; // 后缀和数组int main()
{cin >> n >> m;for (int i = 1; i <= n; i++){int x;cin >> x;mp[x]++; // 统计每个难度出现次数}// 将map转为vector便于处理vector<pair<int, int>> vec(mp.begin(), mp.end());int n = vec.size();// 计算后缀和:s[i]表示难度≥vec[i]的题目总数for (int i = n - 1; i >= 0; i--){s[i] = s[i + 1] + vec[i].second;}int ans = 0;for (int i = 0; i < n; i++){// 如果选择当前难度作为最低难度,是否能有足够题目if (s[i] >= m){// 最大数量不超过当前难度题目数,也不超过mans = max(ans, vec[i].second);}elsebreak; // 后续难度更大,不可能更优}cout << min(ans, m); // 最终结果不超过mreturn 0;
}

六、代码重点细节解释

  1. map<int, int> mp:自动按难度排序并统计频次
  2. 后缀和数组s[i]:快速获取难度≥当前难度的题目总数
  3. 贪心检查:从最小难度开始,一旦发现无法满足条件立即终止
  4. min(ans, m):确保结果不超过题目总数m

七、复杂度分析

  • 时间复杂度:O(nlogn)(map插入和排序的复杂度)
  • 空间复杂度:O(n)(存储频次和后缀和)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com