牛的学术圈 I
牛的学术圈 I
由于对计算机科学的热爱,以及有朝一日成为 「Bessie 博士」的诱惑,奶牛 Bessie 开始攻读计算机科学博士学位。
经过一段时间的学术研究,她已经发表了 篇论文,并且她的第 篇论文得到了来自其他研究文献的 次引用。
Bessie 听说学术成就可以用 指数来衡量。
指数等于使得研究员有至少 篇引用次数不少于 的论文的最大整数 。
例如,如果一名研究员有 篇论文,引用次数分别为 ,则 指数为 ,然而若引用次数为 则 指数将会是 。
为了提升她的 指数,Bessie 计划写一篇综述,并引用一些她曾经写过的论文。
由于页数限制,她至多可以在这篇综述中引用 L 篇论文,并且她只能引用每篇她的论文至多一次。
请帮助 Bessie 求出在写完这篇综述后她可以达到的最大 指数。
注意 Bessie 的导师可能会告知她纯粹为了提升 指数而写综述存在违反学术道德的嫌疑;我们不建议其他学者模仿 Bessie 的行为。
输入格式
输入的第一行包含 和 。
第二行包含 个空格分隔的整数 。
输出格式
输出写完综述后 Bessie 可以达到的最大 指数。
数据范围
,
,
输入样例1:
4 0 1 100 2 3
输出样例1:
2
样例1解释
Bessie 不能引用任何她曾经写过的论文。上文中提到, 的 指数为 。
输入样例2:
4 1 1 100 2 3
输出样例2:
3
样例2解释
如果 Bessie 引用她的第三篇论文,引用数会变为 。上文中提到,这一引用数的 指数为 。
解题思路
这是一个关于指数的问题。的含义为至少篇文章,被引用的次数大于等于,满足这个条件的所有中最大的那个数。
求指数的方法是先将这个序列从大到小进行排序,然后从小到大枚举,如果前篇文章被引用次数都大于等于,那么这个是满足条件的。
在这题中可以选择让其中某些文章增加一次的引用次数,问我们在这个条件下指数最大是多少。
一样先将文章从大到小排序,然后从小到大枚举,这个要成立要满足下面两个条件:
- 由于我们选择的是前篇文章,这篇文章是所有文章里最大的篇,因此这篇中的最小值要大于等于。
- 这篇文章中,引用次数为的文章数量应该小于等于。
由于是从小到大枚举,序列是单调递减的,因此最小值就是第个数,即,因此第一个条件就是要满足。
对于第二个条件,我们就是要找到左边第一个大于等于的数,假设这个数的下标为。由于单调递增,序列单调递减,每次增加,意味着我们要找的左边第一个大于等于的数也要增加,即应该是向左移动的,即是单调减少的。因此有当单调递增,会单调递减,可以用双指针来解决。
证明一下双指针的正确性。如果往后走,增大到,假设也往后走,增大到,那么会有,因为按照规定对应的那个数是第一个大于等于的,因此有,又因为对于而言,第一个大于等于的数应该在这个位置上,但选择也满足且更靠近,因此就矛盾了。因此是单调递减的。
AC代码如下:
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 5 const int N = 1e5 + 10; 6 7 int a[N]; 8 9 int main() { 10 int n, m; 11 scanf("%d %d", &n, &m); 12 for (int i = 1; i <= n; i++) { 13 scanf("%d", a + i); 14 } 15 16 sort(a + 1, a + n + 1, greater<int>()); 17 18 int ret = 0; 19 for (int i = 1, j = n; i <= n; i++) { 20 while (j && a[j] <= i - 1) { // 找到第一个大于等于h的数 21 j--; 22 } 23 if (a[i] >= i - 1 && i - j <= m) ret = i; // 要满足两个条件 24 } 25 26 printf("%d", ret); 27 28 return 0; 29 }
对于第二个条件,还可以开一个数组来记录每篇文章引用次数的个数,直接查是否满足这个条件就可以了。
AC代码如下:
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 5 const int N = 1e5 + 10; 6 7 int a[N], cnt[N]; 8 9 int main() { 10 int n, m; 11 scanf("%d %d", &n, &m); 12 for (int i = 1; i <= n; i++) { 13 scanf("%d", a + i); 14 } 15 16 sort(a + 1, a + n + 1, greater<int>()); 17 18 int ret = 0; 19 for (int i = 1; i <= n; i++) { 20 cnt[a[i]]++; 21 if (a[i] >= i - 1 && cnt[i - 1] <= m) ret = i; 22 } 23 24 printf("%d", ret); 25 26 return 0; 27 }
参考资料
AcWing 3745. 牛的学术圈 I(春季每日一题2022):https://www.acwing.com/video/3736/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/16029021.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探