chenfy27的刷题记录

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

abc373E How to Win the Election

有N个候选人和总共K张选票,目前第i个候选人的票数为A[i]。在全部选票统计完成后,如果得票数多于自己的人数小于M,则当选,可以多个人同时当选。对于每个人,输出当选需要再获得的最少票数。
1<=M<=N<=2E5, 1<=K<=1E12, 0<=A[i]<=1E12, sum(A[i])<=K

分析:对每个候选人,二分答案,假设需要的票数为x,那么最终得票为A[i]+x,大于该得票的人数记为P,则需要统计另外M-P个人的票数进行补齐,看剩下的票数是否足够。

#include <bits/stdc++.h>
using i64 = long long;
// SumTreap模板...
void solve() {
i64 N, M, K;
std::cin >> N >> M >> K;
SumTreap<i64> tr;
std::vector<i64> A(N);
for (int i = 0; i < N; i++) {
std::cin >> A[i];
tr.insert(A[i]);
K -= A[i];
}
if (N == M) {
for (int i = 0; i < N; i++) {
std::cout << " 0";
}
return;
}
auto check = [&](i64 cur, i64 add) {
i64 tar = cur + add;
int cnt1 = tr.gtcnt(tar);
if (cnt1 >= M) {
return false;
}
int cnt2 = M - cnt1;
i64 sum2 = tr.kSum(M) - tr.kSum(cnt1);
i64 diff = cnt2 * (tar + 1) - sum2;
return diff + add > K;
};
std::vector<i64> ans(N);
for (int i = 0; i < N; i++) {
tr.erase(A[i]);
i64 lo = 0, hi = 1E12, mid;
while (lo < hi) {
mid = lo + (hi - lo) / 2;
if (check(A[i], mid)) {
hi = mid;
} else {
lo = mid + 1;
}
}
if (lo <= K) {
ans[i] = lo;
} else {
ans[i] = -1;
}
tr.insert(A[i]);
}
for (int i = 0; i < N; i++) {
std::cout << ans[i] << " ";
}
}
int main() {
std::cin.tie(0)->sync_with_stdio(0);
int t = 1;
while (t--) solve();
return 0;
}

posted on   chenfy27  阅读(15)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示