2022.10.24 总结
1. 逐月 P4988
题意
奶牛 Bessie 发表了 \(n\) 篇论文,并且她的第 \(i\) 篇论文被引用了 \(c_i\) 次。
现在有一个 \(h\) 指数,这个指数等于使得研究员有至少 \(h\) 篇引用次数不少于 \(h\) 的论文的最大整数。
Bessie 希望自己的 \(h\) 指数尽可能高,所以她写了一篇综述,在综述中,她只能引用 \(l\) 次,并且每篇论文最多只能被引用一次。
请你求出 Bessie 能达到的最大的 \(h\) 值。
思路
100 分
首先,先将 \(c\) 从大到小排序,所以 \(c\) 序列就变成了一个非递增序列,也就是 \(c_1 \ge c_2 \ge c_3 \ge \dots \ge c_n\)。
然后,有两种情况:
-
\(l = 0\)。因为 \(l = 0\),所以直接寻找 \(h\) 即可,而已经从大到小排过序了,直接找到最大的 \(c_h \ge h\) 即可。
-
\(l \ne 0\)。在这种情况中,最后答案只有两种情况,\(h\) 或 \(h + 1\)(\(h\) 是前面\(l = 0\) 时的 \(h\))。首先,是 \(h\) 的情况很简单,就是上面那种。因为 \(c_{h + 1}\) 是 \(\le h\) 的,而每篇文章只能引用一次,所以要么是 \(h\),要么是 \(h + 1\)。
\(h\) 是可以直接求出来的,而 \(h + 1\) 则是由 \(1 \sim h + 1\) 中的所有 \(h\) 加上 \(1\) 的得到的,可以用循环求解,也可以先用桶记录。
时间复杂度
求出 \(h\),\(O(n)\)。
循环求 \(h\) 的数量,\(O(n)\)。(用桶的话就没有)
总时间复杂度为 \(O(n)\)。
空间复杂度
记录 \(c_i\),\(O(n)\)。
用桶记录数量,\(O(\max \{c_i\})\)。(循环求解是没有的)
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n, l, c[N], ans;
int main() {
freopen("acowdemia1.in", "r", stdin);
freopen("acowdemia1.out", "w", stdout);
cin >> n >> l;
for (int i = 1; i <= n; i++) {
cin >> c[i];
}
sort(c + 1, c + n + 1);
for (int i = 1; i <= n; i++) {
if (c[n - i + 1] >= i) {
ans = max(ans, i);
} else {
int ct = 0;
bool f = 0;
for (int j = n - i + 1; j <= n; j++) {
if (i > c[j] + 1) {
f = 1;
break;
}
ct += (i > c[j]);
}
if (ct <= l && !f) {
ans = max(ans, i);
} else {
break;
}
}
}
cout << ans;
return 0;
}