BZOJ4868:[SHOI2017]期末考试——题解

http://www.lydsy.com/JudgeOnline/problem.php?id=4868

题目复制于洛谷:https://www.luogu.org/problemnew/show/P3745#sub

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

第i位同学希望在第ti天或之前得知所有课程的成绩。如果在第ti天,有至少一门课程的成绩没有公布,他就会等待最后公布成绩的课程公布成绩,每等待一天就会产生C不愉快度。对于第i门课程,按照原本的计划,会在第bi天公布成绩。

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

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

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

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

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

感觉像三分最终出成绩的时间但是不知道怎么证明于是看了题解。

首先我们考虑如果我们知道最终发成绩的时间的话,那么我们显然能得到此时的唯一最优解。

无脑做法:

显然学生代价C我们立刻能求出来,O(n)无脑。

然后我们考虑AB代价,显然B的操作要比A优秀,所以当B<=A时显然只需要B操作即可。

而且B操作代价求法很无脑,一个O(m)就能求。

考虑A操作,先预处理排好序然后无脑加减就可以做到一个O(m)。

所以综上固定时间求代价的复杂度为O(max(n,m)),且nm数量级一致,简记做O(n)。

再考虑对于学生来说,显然时间越小代价越小。

对于老师来说,显然时间越大代价越大。

复合函数显然满足单峰性,可以三分,是一个log的。

所以是O(nlogn),1e5绝对能过。

(我的代码就是这个)

跑得快做法:

http://www.cnblogs.com/RabbitHu/p/LOJ2141.html提供了一种O(1)求最优解的方法,再套上三分就可以O(logn)了。

但是相比较而言无脑做法十分的妙(因为无脑啊!考试的时候谁还带脑子……)。

#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+5;
inline int read(){
    int X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch==‘-‘;ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
ll A,B,C;
int n,m,t[N],b[N],nb[N];
inline ll suan(int ed){
    ll ans=0;
    for(int i=1;i<=n;i++){
        if(t[i]<ed)ans+=(ed-t[i])*C;
        else break;
    }
    for(int i=1;i<=m;i++)nb[i]=b[i];
    if(A<B){
        int l=1,r=m;
        while(l<r){
            if(nb[r]>ed){
                int delta=ed-nb[l];
                if(delta<0)break;
                if(nb[r]-delta>ed){
                    nb[r]-=delta;
                    nb[l++]=ed;
                    ans+=A*delta;
                }else{
                    ans+=A*(nb[r]-ed);
                    nb[l]+=nb[r]-ed;
                    nb[r--]=ed;
                }
            }else break;
        }
    }
    for(int i=m;i>=1;i--){
        if(nb[i]>ed)ans+=(nb[i]-ed)*B;
    }
    return ans;
}
ll sanfen(int l,int r){
    while(233){
        if(r-l<3){
            ll ans=suan(r);
            for(int i=l;i<r;i++)ans=min(ans,suan(i));
            return ans;
        }
        int mid1=l+(r-l)/3,mid2=mid1+(r-l)/3;
        if(suan(mid1)>suan(mid2))l=mid1;
        else r=mid2;
    }
}
int main(){
    A=read(),B=read(),C=read();
    n=read(),m=read();
    for(int i=1;i<=n;i++)t[i]=read();
    for(int i=1;i<=m;i++)b[i]=read();
    sort(t+1,t+n+1);sort(b+1,b+m+1);
    printf("%lld\n",sanfen(t[1],max(t[n],b[m])));
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

原文地址:https://www.cnblogs.com/luyouqi233/p/8452709.html

时间: 2024-10-15 06:55:07

BZOJ4868:[SHOI2017]期末考试——题解的相关文章

bzoj4868 [Shoi2017]期末考试

4868: [Shoi2017]期末考试 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 961  Solved: 437[Submit][Status][Discuss] Description 有n位同学,每位同学都参加了全部的m门课程的期末考试,都在焦急的等待成绩的公布.第i位同学希望在第ti天 或之前得知所.有.课程的成绩.如果在第ti天,有至少一门课程的成绩没有公布,他就会等待最后公布成绩的课程 公布成绩,每等待一天就会产生C不愉快度.对

【bzoj4868】[Shoi2017]期末考试 前缀和

题目描述 有n位同学,每位同学都参加了全部的m门课程的期末考试,都在焦急的等待成绩的公布.第i位同学希望在第ti天或之前得知所.有.课程的成绩.如果在第ti天,有至少一门课程的成绩没有公布,他就会等待最后公布成绩的课程公布成绩,每等待一天就会产生C不愉快度.对于第i门课程,按照原本的计划,会在第bi天公布成绩.有如下两种操作可以调整公布成绩的时间:1.将负责课程X的部分老师调整到课程Y,调整之后公布课程X成绩的时间推迟一天,公布课程Y成绩的时间提前一天:每次操作产生A不愉快度.2.增加一部分老师

【BZOJ4868】期末考试(整数三分)

题意: 有n位同学,每位同学都参加了全部的m门课程的期末考试,都在焦急的等待成绩的公布.第i位同学希望在第ti天 或之前得知所.有.课程的成绩.如果在第ti天,有至少一门课程的成绩没有公布,他就会等待最后公布成绩的课程 公布成绩,每等待一天就会产生C不愉快度.对于第i门课程,按照原本的计划,会在第bi天公布成绩.有如下两种 操作可以调整公布成绩的时间:1.将负责课程X的部分老师调整到课程Y,调整之后公布课程X成绩的时间推迟一天 ,公布课程Y成绩的时间提前一天:每次操作产生A不愉快度.2.增加一部

【BZOJ4868】期末考试 [三分][贪心]

期末考试 Time Limit: 20 Sec  Memory Limit: 512 MB[Submit][Status][Discuss] Description Input Output Sample Input 100 100 2 4 5 5 1 2 3 1 1 2 3 3 Sample Output 6 HINT Solution 首先,由于学生需要知道所有的成绩,这意味着即使只有一个成绩不知道,代价也是要算的,那么显然答案只和所有成绩都发出的时间有关. 显然,如果我们知道了所有成绩都发

三分 BZOJ4868 [Sxoi2017] 期末考试

4868: [Sxoi2017]期末考试 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 605  Solved: 270[Submit][Status][Discuss] Description 有n位同学,每位同学都参加了全部的m门课程的期末考试,都在焦急的等待成绩的公布.第i位同学希望在第ti天 或之前得知所.有.课程的成绩.如果在第ti天,有至少一门课程的成绩没有公布,他就会等待最后公布成绩的课程 公布成绩,每等待一天就会产生C不愉快度.对

bzoj 4868: [Shoi2017]期末考试

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

[Shoi2017]期末考试

题目描述 有n位同学,每位同学都参加了全部的m门课程的期末考试,都在焦急的等待成绩的公布. 第i位同学希望在第ti天或之前得知所有课程的成绩.如果在第ti天,有至少一门课程的成绩没有公布,他就会等待最后公布成绩的课程公布成绩,每等待一天就会产生C不愉快度.对于第i门课程,按照原本的计划,会在第bi天公布成绩. 有如下两种操作可以调整公布成绩的时间: 1.将负责课程X的部分老师调整到课程Y,调整之后公布课程X成绩的时间推迟一天,公布课程Y成绩的时间提前一天:每次操作产生A不愉快度. 2.增加一部分

【bzoj4868】期末考试

我还第一次见到省选考三分--? #include<bits/stdc++.h> #define N 200005 using namespace std; typedef long long ll; int n,m,r,t[N],b[N]; ll a,B,c,ans; ll calc(int p){ ll x=0,y=0; for(int i=1;i<=m;i++)if(b[i]<p)x+=p-b[i];else y+=b[i]-p; return a<B?min(x,y)*

BZOJ 4868 [Shoi2017]期末考试 ——三分 枚举

考场上xjb三分过掉了. 然后$sdfzyhx$.$silvernebula$ $O(n)$虐掉了. 我还是太菜了 #include <cstdio> #include <cmath> #include <queue> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=