NC20439 [SHOI2017]期末考试

题目

题目描述

n 位同学,每位同学都参加了全部的 m 门课程的期末考试,都在焦急的等待成绩的公布。第 i 位同学希望在第 ti 天或之前得知所有课程的成绩。如果在第ti天,有至少一门课程的成绩没有公布,他就会等待最后公布成绩的课程公布成绩,每等待一天就会产生 C 不愉快度。对于第 i 门课程,按照原本的计划,会在第 bi 天公布成绩。有如下两种操作可以调整公布成绩的时间:

1.将负责课程 X 的部分老师调整到课程 Y ,调整之后公布课程 X 成绩的时间推迟一天,公布课程 Y 成绩的时间提前一天;每次操作产生 A 不愉快度。

2.增加一部分老师负责学科 Z ,这将导致学科 Z 的出成绩时间提前一天;每次操作产生 B 不愉快度。

上面两种操作中的参数 X,Y,Z 均可任意指定,每种操作均可以执行多次,每次执行时都可以重新指定参数。

现在希望你通过合理的操作,使得最后总的不愉快度之和最小,输出最小的不愉快度之和即可

输入描述

第一行三个非负整数 A,B,C ,描述三种不愉快度,详见【问题描述】;
第二行两个正整数 n,m(1n,m105) , 分别表示学生的数量和课程的数量;
第三行 n 个正整数 ti ,表示每个学生希望的公布成绩的时间;
第四行 m 个正整数 bi ,表示按照原本的计划,每门课程公布成绩的时间。
1N,M,Ti,Bi100000,0A,B,C100000

输出描述

输出一行一个整数,表示最小的不愉快度之和。

示例1

输入

100 100 2
4 5
5 1 2 3
1 1 2 3 3

输出

6

说明

由于调整操作产生的不愉快度太大,所以在本例中最好的方案是不进行调整; 全部
5 的门课程中,最慢的在第 3 天出成绩;
同学 1 希望在第 5 天或之前出成绩,所以不会产生不愉快度;
同学 2 希望在第 1 天或之前出成绩,产生的不愉快度为 (3 - 1) * 2 = 4;
同学 3 希望在第 2 天或之前出成绩,产生的不愉快度为 (3 - 2) * 2 = 2;
同学 4 希望在第 3 天或之前出成绩,所以不会产生不愉快度;
不愉快度之和为 4 + 2 = 6 。

备注

数据范围

img

题解

知识点:三分。

三分最晚的公布的时间,因为其符合单调性,晚于或早于这个时间的最晚公布时间造成的不满意度都会变大,B则答案时间在峰谷。

通过计算最晚时间 mid 的最优不满意度进行检验答案。先遍历数组计算超时总额 need 和多余总额 restrest 用于操作 1 。注意到,若 AB 肯定优先用操作 2 提前所有超时课的公布时间,花费是 Bneed ;若 A<B ,优先用操作 1 ,但可能 rest 不够,需要用操作 2 补齐剩余的 need ,够用的花费是 Aneed ,不够用的花费是 Arest+B(needrest) 。最后累加 Cmax(midT[i]) ,得到调整后的学生不满意度,返回花费总和进行比较。

时间复杂度 O((m+n)logBmax)

空间复杂度 O(m+n)

代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll a, b, c;
int n, m;
int T[100007], B[100007];
ll calc(int mid) {
ll need = 0, rest = 0, ans = 0;
for (int i = 0;i < m;i++) {
if (B[i] <= mid) rest += mid - B[i];
else need += B[i] - mid;
}
if (b <= a) ans += need * b;
else {
if (need <= rest) ans += need * a;
else ans += rest * a + (need - rest) * b;
}
for (int i = 0;i < n;i++) ans += max(mid - T[i], 0) * c;
return ans;
}
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> a >> b >> c >> n >> m;
for (int i = 0;i < n;i++) cin >> T[i];
for (int i = 0;i < m;i++) cin >> B[i];
int l = 1, r = *max_element(B, B + m);
while (l <= r) {
int mid1 = l + (r - l) / 3;
int mid2 = r - (r - l) / 3;
if (calc(mid1) <= calc(mid2)) r = mid2 - 1;
else l = mid1 + 1;
}
cout << calc(l) << '\n';
return 0;
}
posted @   空白菌  阅读(72)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示