传送门:洛谷 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;
}
最后修改:2025 年 03 月 26 日
如果觉得我的文章对你有用,请随意赞赏