传送门:洛谷 CF2091B Team Training | Codeforces B. Team Training
更佳的阅读体验:CF2091B 题解
简要题意:给定长度为 $n$ 的序列 $a$,将序列划分为 $k$ 段,使得尽可能多的段中最小元素与段长的乘积不小于 $x$。求 $k$ 的值。
读完题我们首先可以自然地想到:当某个元素已经不小于 $x$ 时,它自己就可以成为一个单独的段。也就是说,越大的元素越容易成为单独的一段。
由此我们想到贪心。我们将序列 $a$ 从大到小排序,那么排在前面的元素如果可以成为一段,那么这个段的长度一定是较小的。因此排序后我们从头到尾遍历整个序列,每当可以构成一段就给答案 $+1$。可以证明这样的贪心策略是正确的。
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 2e5 + 10;
int t, n, x, a[N], last, ans;
int main() {
cin.tie(nullptr);
ios::sync_with_stdio(false);
for (cin >> t; t; --t) {
ans = last = 0;
cin >> n >> x;
for (int i = 1; i <= n; ++i) cin >> a[i];
sort(a + 1, a + n + 1, greater<>());
for (int i = 1; i <= n; ++i)
if (a[i] * (i - last) >= x) {
++ans;
last = i;
continue;
}
cout << ans << '\n';
} return 0;
}