zoukankan      html  css  js  c++  java
  • [luogu] P3745 [六省联考2017]期末考试 (贪心)

    P3745 [六省联考2017]期末考试

    题目描述

    (n) 位同学,每位同学都参加了全部的 (m) 门课程的期末考试,都在焦急的等待成绩的公布。

    (i) 位同学希望在第 (t_i)​ 天或之前得知所有课程的成绩。如果在第 (t_i) 天,有至少一门课程的成绩没有公布,他就会等待最后公布成绩的课程公布成绩,每等待一天就会产生 (C) 不愉快度。

    对于第 (i) 门课程,按照原本的计划,会在第 (b_i)​ 天公布成绩。

    有如下两种操作可以调整公布成绩的时间:

    1. 将负责课程 (X) 的部分老师调整到课程 (Y),调整之后公布课程 (X) 成绩的时间推迟一天,公布课程 (Y) 成绩的时间提前一天;每次操作产生 (A) 不愉快度。
    2. 增加一部分老师负责学科 (Z),这将导致学科 (Z) 的出成绩时间提前一天;每次操作产生 (B) 不愉快度。

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

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1: 复制

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

    输出样例#1: 复制

    6

    输入样例#2: 复制

    3 5 4
    5 6
    1 1 4 7 8
    2 3 3 1 8 2

    输出样例#2: 复制

    33

    说明

    【样例 1 说明】

    由于调整操作产生的不愉快度太大,所以在本例中最好的方案是不进行调整; 全部

    5 的门课程中,最慢的在第 3 天出成绩;

    同学 1 希望在第 5 天或之前出成绩,所以不会产生不愉快度;

    同学 2 希望在第 1 天或之前出成绩,产生的不愉快度为 (3 − 1) ∗ 2 = 4;

    同学 3 希望在第 2 天或之前出成绩,产生的不愉快度为 (3 − 2) ∗ 2 = 2;

    同学 4 希望在第 3 天或之前出成绩,所以不会产生不愉快度;

    不愉快度之和为 4 + 2 = 6 。

    题解

    整个题目的贪心在于如何处理(A<B),因为,(A)的使用会伴随着一门科目的推迟,也就是说(A)的使用次数是有限的。

    注意到整个题目的意思就是要我们提前天数,那么我们可以考虑枚举天数,网上使用三分和二分的大佬们实在是太巨辣,我只会(O(n))
    那么当(A<B)的时候,我们就根据天数的推移用前缀和统计一下能有几天可以推迟,然后计算(A)使用的次数,不够的再用(B)提前。
    整个难点就在于学生和科目随时间的线性变化,要自己理一理。
    我们用一个桶记录学生忍耐的时间,另一个记录科目出成绩的时间。
    那么随时间线性变化便是,
    每往后一天,记录这天前有多少科目是可以推迟的,对于推迟的贡献,
    有多少学生是开始忍耐不了的。
    有多少科目是还需要提前的,对于提前一共要多少天。
    自己好好想一下。不懂可以看代码。

    Code

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #define ll unsigned long long
    using namespace std;
    const ll MAXN=1e6+5;
    ll a,b,c,n,m,N,M,sum,ans=1e18,tot;
    ll ti[MAXN],bi[MAXN],bac1[MAXN],bac2[MAXN];
    ll s,ss,tt,t1,t2,t3;
    ll read(){
        ll x=0,w=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*w;
    }
    int main(){
        a=read();b=read();c=read();
        n=read();t2=m=read();
        for(ll i=1;i<=n;i++)ti[i]=read(),bac1[ti[i]]++;
        for(ll i=1;i<=m;i++)bi[i]=read(),bac2[bi[i]]++,ss+=bi[i];
        for(ll i=1;i<=100000;i++){
            //tt当前不能忍受的人的天数,ss当前需要提前的天数,s是当前可以做贡献的天数
            tt+=bac1[i-1]+t1;t1+=bac1[i-1];
            t2-=bac2[i];ss-=bac2[i]+t2;
            s+=bac2[i-1]+t3;t3+=bac2[i-1];
            sum=tt*c;tot=0;
            if(a<b){
                tot=min(ss,s);sum+=min(ss,s)*a;
            }
            sum=sum+max((ss-tot),(ll)0)*b;
            ans=min(ans,sum);
        }
        cout<<ans<<endl;
        return 0;
    }
    
  • 相关阅读:
    海康API——获取监控点预览取流URL,获取的rtsp流不能播放
    MySQL——ON DUPLICATE KEY UPDATE添加索引值实现重复插入变更update
    maven——pom.xml的Missing artifact net.sf.json-lib:json-lib:jar:2.4 报错问题(两种有效的解决方案)
    Mysql——navicat如何导出mysql数据表结构
    MySQL——导入导出.sql文件
    仅用U盘就可以去除XP管理员密码
    测试

    navicat 或者workbench 无法连接127.0.0.1(61)的解决方法
    在linux中添加ftp用户,并设置相应的权限
  • 原文地址:https://www.cnblogs.com/hhh1109/p/10667144.html
Copyright © 2011-2022 走看看