[BZOJ4868][Shoi2017]期末考试

本文分享了一道省选模拟赛中的签到题解题思路与代码实现。通过分别对题目和学生数据排序,采用快速排序算法,计算最优解以减少等待时间和调度成本。特别考虑了B值过大时的特殊情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

#include <bits/stdc++.h>
#define INF (1LL<<62)
#define N 200050
using 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值