abc373E How to Win the Election

news/2024/10/7 17:20:21/文章来源:https://www.cnblogs.com/chenfy27/p/18450323

有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;template <typename TYPE>
struct SumTreap {struct Node {TYPE data, sum;int rnd, siz, dup, son[2];Node() { data = sum = rnd = siz = dup = son[0] = son[1] = 0; }Node(const TYPE &d, int cnt=1) { init(d, cnt); }void init(const TYPE & d, int cnt) {data = d; dup = siz = cnt; sum = d * cnt; rnd = rand(); son[0] = son[1] = 0;}};SumTreap(int multi=1):multiple(multi) { reset(); }void setmulti(int multi) { multiple = multi; }int newnode(const TYPE & d, int cnt) {if (!reuse.empty()) {int r = reuse.front();reuse.pop_front();node[r].init(d, cnt);return r;}node.push_back({d, cnt});return node.size() - 1;}void reset() { root = 0; node.resize(1); reuse.clear(); }void maintain(int x) {node[x].siz = node[x].dup;node[x].sum = node[x].data * node[x].dup;if (node[x].son[0]) {node[x].siz += node[node[x].son[0]].siz;node[x].sum += node[node[x].son[0]].sum;}if (node[x].son[1]) {node[x].siz += node[node[x].son[1]].siz;node[x].sum += node[node[x].son[1]].sum;}}void rotate(int d, int &r) {int k = node[r].son[d^1];node[r].son[d^1] = node[k].son[d];node[k].son[d] = r;maintain(r);maintain(k);r = k;}void insert(const TYPE &data, int cnt, int &r) {if (r) {if (!(data < node[r].data) && !(node[r].data < data)) {if (multiple) {node[r].dup += cnt;maintain(r);}} else {int d = data < node[r].data ? 0 : 1;int u = node[r].son[d];insert(data, cnt, u);node[r].son[d] = u;if (node[node[r].son[d]].rnd > node[r].rnd) {rotate(d^1, r);} else {maintain(r);}}} else {r = newnode(data, cnt);}}TYPE kth(int k) {assert(1 <= k && k <= size());for (int r = root; r; ) {int x = node[r].son[0] ? node[node[r].son[0]].siz : 0;int y = node[r].dup;if (k <= x) {r = node[r].son[0];} else if (k <= x + y) {return node[r].data;} else {k -= x + y;r = node[r].son[1];}}assert(k == 0);return 0;}TYPE Kth(int k) {assert(1 <= k && k <= size());for (int r = root; r; ) {int x = node[r].son[1] ? node[node[r].son[1]].siz : 0;int y = node[r].dup;if (k <= x) {r = node[r].son[1];} else if (k <= x + y) {return node[r].data;} else {k -= x + y;r = node[r].son[0];}}assert(k == 0);return 0;}TYPE ksum(int k) {assert(0 <= k && k <= node[root].siz);TYPE ans = 0;for (int r = root; r && k; ) {int x = node[r].son[0] ? node[node[r].son[0]].siz : 0;int y = node[r].dup;if (k <= x) {r = node[r].son[0];} else if (k <= x + y) {ans += node[node[r].son[0]].sum + node[r].data * (k - x);k = 0;} else {ans += node[node[r].son[0]].sum + node[r].data * y;k -= x + y;r = node[r].son[1];}}return ans;}TYPE kSum(int k) {assert(0 <= k && k <= node[root].siz);TYPE ans = 0;for (int r = root; r && k; ) {int x = node[r].son[1] ? node[node[r].son[1]].siz : 0;int y = node[r].dup;if (k <= x) {r = node[r].son[1];} else if (k <= x + y) {ans += node[node[r].son[1]].sum + node[r].data * (k - x);k = 0;} else {ans += node[node[r].son[1]].sum + node[r].data * y;k -= x + y;r = node[r].son[0];}}return ans;}void erase(const TYPE& data, int cnt, int & r) {if (r == 0) return;int d = -1;if (data < node[r].data) {d = 0;} else if (node[r].data < data) {d = 1;}if (d == -1) {node[r].dup -= cnt;if (node[r].dup > 0) {maintain(r);} else {if (node[r].son[0] == 0) {reuse.push_back(r);r = node[r].son[1];} else if (node[r].son[1] == 0) {reuse.push_back(r);r = node[r].son[0];} else {int dd = node[node[r].son[0]].rnd > node[node[r].son[1]].rnd ? 1 : 0;rotate(dd, r);erase(data, cnt, node[r].son[dd]);}}} else {erase(data, cnt, node[r].son[d]);}if (r) maintain(r);}int ltcnt(const TYPE &data) {int ans = 0;for (int r = root; r; ) {int x = node[r].son[0] ? node[node[r].son[0]].siz : 0;if (node[r].data < data) {ans += node[r].dup + x;r = node[r].son[1];} else if (data < node[r].data) {r = node[r].son[0];} else {ans += x;break;}}return ans;}int gtcnt(const TYPE &data) {int ans = 0;for (int r = root; r; ) {int x = node[r].son[1] ? node[node[r].son[1]].siz : 0;if (node[r].data < data) {r = node[r].son[1];} else if (data < node[r].data) {ans += node[r].dup + x;r = node[r].son[0];} else {ans += x;break;}}return ans;}int count(const TYPE &data) {for (int r = root; r; ) {if (data < node[r].data) {r = node[r].son[0];} else if (node[r].data < data) {r = node[r].son[1];} else {return node[r].dup;}}return 0;}std::pair<bool,TYPE> prev(const TYPE &data) {std::pair<bool,TYPE> ans = {false, 0};for (int r = root; r; ) {if (node[r].data < data) {if (ans.first) {ans.second = std::max(ans.second, node[r].data);} else {ans = {true, node[r].data};}r = node[r].son[1];} else {r = node[r].son[0];}}return ans;}       std::pair<bool,TYPE> next(const TYPE &data) {std::pair<bool,TYPE> ans = {false, 0};for (int r = root; r; ) {if (data < node[r].data) {if (ans.first) {ans.second = std::min(ans.second, node[r].data);} else {ans = {true, node[r].data};}r = node[r].son[0];} else {r = node[r].son[1];}}return ans;}std::vector<Node> node;std::deque<int> reuse;int root, multiple;void insert(const TYPE& data, int cnt=1) { insert(data, cnt, root); }void erase(const TYPE& data, int cnt=1) { erase(data, cnt, root); }int size() const { return root ? node[root].siz : 0; }int lecnt(const TYPE& data) { return size() - gtcnt(data, root); }int gecnt(const TYPE& data) { return size() - ltcnt(data, root); }
};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() {int t = 1;while (t--) solve();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/809504.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中国大学生程序设计竞赛(秦皇岛)正式赛东北大学秦皇岛分校(SMU Autumn 2024 Team Round 1)

中国大学生程序设计竞赛(秦皇岛)正式赛东北大学秦皇岛分校(SMU Autumn 2024 Team Round 1) Problem A. 贵校是构造王国吗 I 思路 官方题解很清晰明了。代码 #include <bits/stdc++.h> using namespace std; #define int long long #define endl \n #define PII pair&…

多校 A 层冲刺 NOIP2024 模拟赛 03

多校 A 层冲刺 NOIP2024 模拟赛 03 T1 五彩斑斓(colorful) 签到题 直接暴力枚举是 \(O(n^4)\) ,考虑使用 \(bitset\) 优化,对每个点开个 \(bitset\),预处理它所在一行它及它之前相同颜色的位置,这样就只用枚举另一个点所在列,时间复杂度为 \(O(n^3+\frac{n^4}{w})\)。 T…

在浏览器上访问媒体资源配置【文件上传】

1.根urls.py文件中 from django.contrib import admin from django.urls import path, include, re_path from django.views.static import serve from django.conf import settingsurlpatterns = [# path(admin/, admin.site.urls),path(api/shipper/, include(apps.shipper.u…

高级程序语言设计第二次作业

姓名:袁志华 班级:软件工程2班 学号:102400231 班级网址:https://edu.cnblogs.com/campus/fzu/2024C 作业网址:https://edu.cnblogs.com/campus/fzu/2024C/homework/13282 图片: 第一题: 第二题: 第三题: 第四题: 第五题: 第六题: 第七题: 第八题:程序清单: 3.1…

macOS Sequoia 15.0.1 (24A348) 正式版 ISO、IPSW、PKG 下载

macOS Sequoia 15.0.1 (24A348) 正式版 ISO、IPSW、PKG 下载macOS Sequoia 15.0.1 (24A348) 正式版 ISO、IPSW、PKG 下载 iPhone 镜像、Safari 浏览器重大更新和 Apple Intelligence 等众多全新功能令 Mac 使用体验再升级 请访问原文链接:https://sysin.org/blog/macOS-Sequoi…

人群聚集监测预警系统

人群聚集监测预警系统采用AI视频智能分析技术,人群聚集监测预警系统通过在工地、工厂等场所已经安装监控摄像头,人群聚集监测预警系统对人员聚集情况进行实时监测,当人群聚集过于密集时,系统将自动发出警报,人群聚集监测预警系统并通过人工智能算法对人员的状态进行识别和…

智能烟火识别预警软件

智能烟火识别预警软件采用人工智能技术,智能烟火识别预警软件在工厂、工地等场所利用已经安装的摄像头,智能烟火识别预警软件对场内的烟花爆竹进行实时监测。当场内出现烟花爆竹时,智能烟火识别预警软件将自动发出警报,并通过人工智能算法通知现场管理人员进行处理。智能烟…

脱岗监测预警系统

脱岗监测预警系统可以通过对工人的位置进行实时监测,脱岗监测预警系统识别是否存在脱岗行为,并及时发出警报。脱岗监测预警系统在工作过程中,如果工人离开其工作位置,脱岗监测预警系统会自动识别并发出警报,提醒管理人员采取措施防止事故的发生。脱岗监测预警系统可以通过…

非煤矿山电子封条系统部署方案

非煤矿山电子封条系统部署方案是基于Ai视频图像识别技术,非煤矿山电子封条系统部署方案通过人工智能算法在矿山设备上安装电子封条,监控矿山矿井出入井人员、人员变化及非煤矿山生产作业状态等状况,及时发现处理非煤矿山异常动态将自动发出警报,及时通知现场管理人员进行处…

加油站员工行为监测预警系统

加油站员工行为监测预警系统可以通过对加油站员工进行实时监控,加油站员工行为监测预警系统识别是否存在不规范行为,并及时发出警报。在卸油作业过程中,加油站员工行为监测预警系统监测员工灭火器的正确放置、静电释放操作规范等作业状态,及时发出警报,提醒工作人员采取措…

矿山电子封条系统

矿山电子封条系统通过在煤矿关键地点安装摄像机以及边缘智能分析终端,矿山电子封条系统实时监测分析煤矿生产作业状态和矿井出入井人员、人数变化等情况,矿山电子封条系统利用智能化视频识别等技术及时发现煤矿异常动态,全天候不间断自动推送报警信息。相比传统的安全监管手…

硬盘咔咔异响数据恢复

当硬盘发出咔咔异响时,这通常表明硬盘可能遇到了严重的问题,如读写头故障、硬盘盘片损坏、电机或主板故障等。此时,数据恢复成为了一个关键的问题。以下是一些建议的数据恢复步骤和注意事项: 一、立即停止使用 一旦发现硬盘发出咔咔异响,应立即停止使用,避免进一步损坏硬…