题目链接
AtCoder Beginner Contest 373 E
思路
很明显,答案是具有单调性的,我们考虑二分答案。
我们定义 s s s数组为 a a a数组从大到小排序后的前缀和数组。
对于排序后的第 i i i个数,我们假设给其增加 x x x票(通过二分答案确定),若是想要其当选,则将剩下的 k − x k-x k−x票给其他候选者之后,比 a [ i ] + x a[i]+x a[i]+x多的不得大于 m m m个。
因此我们可以在前缀和数组上再次二分,直接判断 x x x是否可行即可。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 5;
const int inf = 0x3f3f3f3f3f3f3f3f;
int n, m, k;
int b[N], s[N];
struct node
{
int a, id, ans;
} p[N];
void solve()
{
cin >> n >> m >> k;
for (int i = 1; i <= n; i++)
{
cin >> p[i].a;
p[i].id = i;
k -= p[i].a;
}
sort(p + 1, p + 1 + n, [&](node x, node y) {return x.a > y.a;});
for (int i = 1; i <= n; i++)
{
s[i] = s[i - 1] + p[i].a;
b[i] = p[n - i + 1].a;
}
for (int i = 1; i <= n; i++)
{
if (p[i].a == p[i - 1].a)
{ //特殊情况
p[i].ans = p[i - 1].ans;
continue;
}
if (p[i].a + k < p[m].a)
{
p[i].ans = -1;
continue;
}
if (i <= m)
{
int res = (m + 1 - i) * p[i].a - (s[m + 1] - s[i]) + (m + 1 - i);
if (res > k)
p[i].ans = 0;
else
{
int low = 1, high = k;
while (low < high)
{
int mid = low + high >> 1;
auto check = [&](auto check, int x)->bool{
int op = p[i].a + x;
int tmpk = k - x;
int idx = upper_bound(b + 1, b + 1 + n, op) - b;
idx = n - idx + 1;
int res = (m + 1 - idx - 1) * op - (s[m + 1] - s[idx]) + p[i].a + (m + 1 - idx - 1);
return res <= tmpk;
};
if (check(check, mid))
{
low = mid + 1;
}
else high = mid;
}
p[i].ans = high;
}
}
else
{
int low = 1, high = k;
while (low < high)
{
int mid = low + high >> 1;
auto check = [&](auto check, int x)->bool{
int op = p[i].a + x;
int tmpk = k - x;
int idx = upper_bound(b + n - m + 1, b + 1 + n, op) - b;
idx = n - idx + 1;
int res = (m - idx) * op - (s[m] - s[idx]) + (m - idx);
return res <= tmpk;
};
if (check(check, mid))
{
low = mid + 1;
}
else high = mid;
}
p[i].ans = high;
}
}
sort(p + 1, p + 1 + n, [&](node x, node y) {return x.id < y.id;});
for (int i = 1; i <= n; i++)
{
cout << p[i].ans << " ";
}
cout << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int test = 1;
// cin >> test;
for (int i = 1; i <= test; i++)
{
solve();
}
return 0;
}