周报素材
A. Set or Decrease
题意:
给定一个长度为n的数组给一个数k,你可以进行一下两种操作
1.数组中的一个数减1
2.用数组中的一个数赋值给数组中的另一个数
(操作1 2 等价)
要求操作次数最小,使数组的和小于等于k
思路:
有两个变量
易得,操作一多,则操作二少
操作一少,则操作二多
枚举操作二的数量,O(n)
当操作二的数量确定,O(1)算出所需的操作一数:ceil((now-k)*1.0/(n-i+1))
即得到最小答案
`
ll ans = 2e18;
cin >> n >> k;
for (int i = 1; i <= n; i++) cin >> s[i];
sort(s + 1, s + 1 + n);
for (int i = 1; i <= n; i++) pre[i] = pre[i - 1] + s[i];
for (int i = 1; i <= n; i++)
{
ll now = pre[i] + (n - i) * s[1];//先假设拿a[1]换掉最后n-i个数可行
if (now <= k) ans = min(ans, ll(n - i));//如果可行,直接比较答案
else//换掉最后n-i数不可行,那么补救的方案就是使a[1]减1
{ //te表示应当再使a[1]减几次1才可行。now-k表示多余的要减掉的
ll te = ceil((now - k) * 1.0 / (n - i + 1));//分给a[1]和后n-i个数,就等于每1个要减的数,
//即a[1]要减的数。ceil向上取整
ans = min(ans, ll(n - i + te));
}
}
cout << ans << endl;
`