Loading

12.26 CW 模拟赛 T1. 平均

思路

首先你发现假设当前的平均数是 \(a\) , 其中 \(\lceil a \rceil = k\) , 那么你势必要选上所有 \(< k\) 的数来拉低平均数, 然后贪心的从小到大选 \(\geq k\) 的数来提高贡献

如果想不到也可以这样想, 对于一个确定的平均数, 一定要尽可能的让比平均数小的数更多, 才能更多的腾出空间给大于平均数的数

显然的, 这样子搞完之后, 每次选择的一定是一段排序后数列的前缀, 你对前缀做一点二分操作就可以计算出答案了


以下是赛时想歪之后的思路, 我看看还能不能救回来

赛时发现, 最优解可以看做把排序后的数列 (以下简称数列) 分成两段, 分别取两端的前缀组合就可以找到一个不劣的答案

其实容易发现, 每次假设把 \(a\) 数列分成两部分 \(u, v\) , 那么显然的, 如果你对于一个确定的 \(v\) 进行分析, \(u\) 一定是选完 \(v\) 之前的所有最优, 也就是说 \(u, v\) 显然连在了一起拼成了前缀

代码

没有难度, 脑子没转过来

#include <bits/stdc++.h>
// #define FILE_IO
#define int long long
const int MAXN = 1e6 + 20;

int n;
int a[MAXN];

class Brute_Force
{
private:
    int Ans = 0;

public:
    void solve() {
        std::sort(a + 1, a + n + 1);

        for (int p = n; p >= 1; p--) {
            int rsum = 0;
            for (int r = p; r <= n; r++) {
                rsum += a[r];
                int lsum = 0; bool flag = false;
                for (int l = 1; l < p; l++) {
                    lsum += a[l];
                    if ((r - p + 1ll + l) * a[p] > lsum + rsum) {
                        Ans = std::max(Ans, r - p + 1ll);
                    }
                }
            }
        }
        printf("%lld", Ans);
    }
} BF;

class Greedy
{
private:
    int binsearch(int l, int r, int sum, int num) {
        int Left = l, Right = r + 1;
        while (Left < Right) {
            int Mid = (Left + Right) >> 1;
            if (a[Mid] * num > sum) Right = Mid;
            else Left = Mid + 1;
        }
        return Left;
    }

public:
    void solve() {
        std::sort(a + 1, a + n + 1);
        int sum = 0;
        int ans = 0;
        for (int i = 1; i <= n; i++) {
            sum += a[i];
            int res = binsearch(1, i, sum, i);
            ans = std::max(ans, i - res + 1);
        }
        printf("%lld", ans);
    }
} GR;

signed main()
{
#ifdef FILE_IO
    freopen("average5.in", "r", stdin);
    freopen("average5.out", "w", stdout);
#endif
    scanf("%lld", &n);
    for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);

    // if (n <= 500) BF.solve();
    GR.solve();

    return 0;
}

总结

平均数很好的性质, 贪心策略的应用

如果赛时思维想糊了考虑化枚举为单点的正确性, 对于简单题来说一般是这样的

最好是因为难受才没有做出来, 说不定就是菜

posted @ 2024-12-26 15:18  Yorg  阅读(22)  评论(0)    收藏  举报