[BZOJ4868][Shoi2017]期末考试

来源:互联网 发布:获取svn数据java接口 编辑:程序博客网 时间:2024/06/06 09:45

上午做了他们省选的模拟赛
感觉好累啊,没啥状态
这题属于签到题,解法好想也好打,没心情拍,不过最后也算是签到成功了吧

题目和学生可以分开来讨论,对两个数组分别排序
从小到大爆枚最晚出分的时间
分别算出等待的时间和调度的花费更新答案
注意B特别大的时候B一定不会作为最优解,直接特判掉不要算出来,那个值特别大会大于264
时间复杂度取决于排序的复杂度,使用基数排序可以做到O(N),但是这里用了更好写的快速排序,时间复杂度为O(Nlog2N)

#include <bits/stdc++.h>#define INF (1LL<<62)#define N 200050using namespace std;typedef long long LL;int t[N],b[N],n,m,tp,x,y;LL A,B,C,sum;inline int rd() {int r;scanf("%d",&r);return r;}void init() {    A = rd(), B = rd(), C = rd();    n = rd(), m = rd();    for (int _=1;_<=n;_++) t[_] = rd(); sort(t+1,t+n+1);    for (int _=1;_<=m;_++) b[_] = rd(); sort(b+1,b+m+1);}LL calc(LL _, LL x, LL fr) {    LL dmd = sum-fr-_*(m-x), res = min(_*x-fr, dmd);    if (B>N) return res>=dmd ? dmd*A : INF;    return min(1LL*dmd*B, 1LL*res*A+1LL*(dmd-res)*B);}void solve() {    tp = t[n]; x = 1; y = 1;    for (int _=1;_<=m;_++) sum += b[_];    LL S=0LL, fr=0LL, ans=INF;    for (int _=1;_<=tp;_++) {        while (x<=n && t[x] < _) S += t[x++];        while (y<=m && b[y] < _) fr += b[y++];        LL cur = calc(_, y-1, fr);        ans = min(ans, 1LL * C * ( 1LL*(x-1)*_-S ) + cur);    }    cout << ans << endl;}int main() {    init();    solve();    return 0;}