题解 | P3745 [六省联考 2017] 期末考试

alt

题干分析

简要阐述一下题目要我们做什么:

  • n个学生都参加了m门考试.
  • 每位学生对什么时候所有科目成绩均能出有一个预期.
  • 如果某个同学在其预期时间内成绩未完全出,他每多等一天增加C点不愉快度.
  • 现在学校为了减少总体学生的不愉快度,允许我们进行操作提前或延后某门课的出成绩时间.
  • 我们可以使某些课程提前总共k天,同时使某些课程延后总共k天,这样做老师们会产生总计k * A点不愉快度
  • 我们还可以只使某些课程提前总计k天,这样做会让老师们产生总计k * B点不愉快度
  • 题目的核心便是找到一种调节方案,使老师和学生的总不愉快度最小.返回该总不愉快度

算法思路

我们可以预计到总不愉快随操作的变化是个单谷函数(或者单调函数):

  • 我们不妨将所有未达到p要求天数前出成绩的科目通过操作全部达到p时间出成绩,当p=100000(不限制出成绩时间)时即为不进行操作,学生总不愉快度是最高的.
  • 同样的,如果我们将p压缩到1,这时学生的总不愉快度一定为0(虽然听起来很扯就是了),老师的不愉快度此时达到最高.
  • 我们的总值便是这两个对冲变量的和,因而是一个单谷函数(或者单调函数),因此我们使用三分法逼近最小的操作即可得到最小的总不愉快度.

实现代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int n,m;
ll A,B,C,ans;
vector<int> t;
vector<int> b;

ll op(int p) { // 操作所引起的不愉快度(设定操作后所有科目最晚p天后必须出成绩)
    ll x = 0, y = 0; // x为允许推迟的总天数,y为需要提前的总天数
    for (int i = 1; i <= m; ++i) {
        if (b[i] < p) x += p - b[i];
        else y += b[i] - p;
    }
  	// 如果交换天数操作引起的不愉快度更低,我们更倾向于交换天数
  	// 天数不够(y比x大,即需要额外提前某些科目的出成绩时间),我们再强行提前这些科目的出成绩时间
    if (A < B) return min(x,y) * A + (y - min(x, y)) * B;
    return y * B; // 如果强行提前操作反而引起的不愉快度更小,我们直接全部强行提前就行了
}

ll total(int p) { // 最晚p天成绩全出,学生的总不愉快度
    ll sum = 0;
    for (int i = 1; i <= n; ++i) {
        if (t[i] < p) sum += (p - t[i]) * C;
    }
    return sum;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> A >> B >> C;
    cin >> n >> m;

    t.resize(n + 1);
    b.resize(m + 1);

    for (int i = 1; i <= n; ++i) cin >> t[i];
    for (int i = 1; i <= m; ++i) cin >> b[i];

    sort(++t.begin(), t.end());
    sort(++b.begin(), b.end());

    if (C >= 1e16) { // 特判,C极大,我们直接让所有学生满足,苦一苦老师们
        cout << op(t[1]);
        return 0;
    }

    ans = 1e16;
    int left = 1, right = 1e5;
    while (right - left > 2) {
        int mid1 = left + (right - left) / 3, mid2 = right - (right - left) / 3;
        ll c1 = op(mid1) + total(mid1);
        ll c2 = op(mid2) + total(mid2);
        if (c1 <= c2) right = mid2;
        else left = mid1;
    }

    for (int i = left; i <= right; ++i) {
        ll x = op(i) + total(i);
        ans = min(ans, x);
    }
    cout << ans;

    return 0;
}

复杂度分析

  • 时间复杂度: 三分操作次数总计为logk,k为未操作前最后出的成绩所需天数,每次三分比较耗时O(n),共T次测试,假设T次测验n总和为N,总时间复杂度为O(Nlogk).
  • 空间复杂度: 除去存储输入的空间消耗,三分时只使用常数的额外空间,总空间复杂度为O(1).
全部评论

相关推荐

2025年从3月到12月,求职求职求职,整年差不多都给实习和秋招&amp;论文了,所以能给个HappyEnding吗?KS&amp;JD&amp;PDD!!!实习(3-7):3月份开始投递,因为客观原因只投递了几家公司:团子、得子、多子、滴滴约面的团子(两次一面挂,秋招也没给机会了)、得子(暑期OC,可惜为什么不能再爱一次的!!!)、滴滴(二面挂)独自一个人去Shanghai,住的青旅,随时准备**期间还和大学室友玩了一个周末,还是一段不错的回忆实习Mentor和PM也很不错,Leader接触不多,人也很好,但秋招......原因不知道,一句话就是秋招太卷了,暑期大家想着去大公司,秋招多数朝“钱”看感谢接触的业务在秋招面试中很多公司也有类似业务PDD\JD\KS秋招(8-12月甚至明年1月,仍在进行中)8月开始提前批投递,差不多有面,但各种原因挂掉9月面完PDD信心大增(谁想到主管还不审批Offer,整整3个月了,求Offer,牛客最灵了!!!)陆陆续续面完京东(HR快发快OC开奖审批Offer,求OC,等疯了!!!)、快手(收到OfferCall,保佑Offer审批成功!爱手!)、携程(不抱有希望了,可你官网还在补录,可恶!!!)、收钱吧(Offer,也是第一个Offer,可开太低拒掉了)10月老东家(最可惜的,为什么不联系Leader,不够勇气,只能说秋招竞争太激烈,老东家又招的少,只能说给钱是真的,保佑还能开到我,虽然也不抱有很大希望了。)字节(捞了3次,投晚了,全怪PDD给我幻想!!!虽然真的也面不过),小米(面完泡池子,开的低也抱有希望)11月最痛苦,身边大佬们都开了,我的全在泡池子.......也是分享欲最低一个月12月,过山车,1号JD官网挂-2号捞&amp;快手开奖OC。3&amp;4JD捞回,等等等,催PDD希望12月能开个比较满意的,KS给我Offer吧!JD也是!超爱手子和东子的!!!希望有个Offer春招就可以放轻松投递,大家都好运好运!!!求HappyEnding吗?KS&amp;JD&amp;PDD!!!
2025年终总结
点赞 评论 收藏
分享
12-16 14:57
门头沟学院 Java
迷茫的大四🐶:是这样的,我都拿到你这同一水平的offer了,那我接你的offer的意义在哪,我一开始想接你们的offer期待是很高的,希望你们下次继续努力
你今年的保底offer是...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务