模拟赛 T1 好做法

不服来叉

首先肯定要二分答案 k,然后肯定留最大的 k 个数,

考虑删除剩下 nk 个数的策略,肯定是倒着删,考察一下删除倒数第 i 个数的时候到底发生了什么,

这里我们先假设之前 i1 个数可以成功删掉,否则可以在前面判断出不能删,

不妨考虑在删之前 i1 个数的时候,如果 x 有法力值分给了这 i 个数中的 k,视为 xk "进了一位",

那我们就要使得之前 i1 个数对 i 的"进位",也就是分给 i 的法力值尽量少,

显然有策略:对每个数 x,先把法力值分给所有不会产生进位的 ni 个数,剩余的法力值留下来进位,

可以看成是填一个 ini 列的矩阵,每次填一行,多余的法力值留到之后的行,

那这样留到最后一行的进位个数就是 x=1i1vx(i1)(ni)

那么 i 需要分出去的法力值就是 vi 加上进位,也就是 x=1ivx(i1)(ni)

i 只能把法力值分给剩下 ni 个数,所以 x=1ivx(i1)(ni)ni,如果满足条件那 i 就能被删掉,否则 i 删不掉。

#include <cstdio>
#include <algorithm>
#define int long long
using namespace std;
int T, n, a[5000050];
inline int R()
{
    int q = 0;
    char c = getchar();
    while (c < '0' || c > '9')
        c = getchar();
    while (c >= '0' && c <= '9')
        q = q * 10 + c - '0', c = getchar();
    return q;
}
bool C(int k)
{
    int z = 0;
    for (int i = n; i > k; --i)
    {
        z += a[i - k];
        if (z > (n - i + 1) * (i - 1))
            return 0;
    }
    return 1;
}
signed main()
{
    freopen("magic.in", "r", stdin);
    freopen("magic.out", "w", stdout);
    T = R();
    while (T--)
    {
        n = R();
        for (int i = 1; i <= n; ++i)
            a[i] = R();
        sort(a + 1, a + n + 1);
        int l = 1, r = n;
        while (l <= r)
        {
            int m = l + r >> 1;
            if (C(m))
                r = m - 1;
            else
                l = m + 1;
        }
        printf("%lld\n", l);
        for (int i = 1; i <= n; ++i)
            a[i] = 0;
    }
    return 0;
}
posted @   Jijidawang  阅读(47)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示