Codeforces Global Round
Round 2
*CF1119G
非常厉害的题
有 \(m\) 个敌人,第 \(i\) 个敌人的生命值为 \(hp_i\)。我方有 \(n\) 个人,需要将 \(n\) 个人分为 \(m\) 组,进行若干轮攻击。每一轮攻击,每一组可以任意选择一个敌人进行攻击,使其生命值减去组中的人数。求最少需要进行多少轮攻击才能使得所有敌人的血量值非正,并给出方案。
\(1\le m\le n\le 10^{6}\),\(1\le hp_i\le 10^{6}\)。
解法
答案的下界是 \(\lceil\frac{\sum hp_i}{n}\rceil\),考虑如何取到这个下界。一种巧妙的办法是,所有人先攻击第一个敌人,当第一个敌人生命值小于 \(n\) 时,分出 \(hp_1\bmod n\) 人攻击一号敌人,剩下的攻击二号敌人。那么还需要分出 \((hp_1+hp_2)\bmod n\) 人攻击第二个敌人,以此类推。那么每一个敌人都能被恰好攻击完(除了最后一个)。
将每一个前缀和对 \(n\) 取模得到数组 \(r\),将 \(r\) 排序,我们希望分组后人数的每一个前缀和对应一个 \(r\),那么只需要对 \(r\) 做差分即可。输出攻击方案只要逐个攻击即可。