[六省联考2017]期末考试

Description:

\(n\) 位同学,每位同学都参加了全部的 \(m\) 门课程的期末考试,都在焦急的等待成绩的公布。
\(i\) 位同学希望在第 \(t_i\) 天或之前得知所有课程的成绩。如果在第 \(t_i\) 天,有至少一门课程的成绩没有公布,他就会等待最后公布成绩的课程公布成绩,每等待一天就会产生 \(C\) 不愉快度。
对于第 \(i\) 门课程,按照原本的计划,会在第 \(b_i\) 天公布成绩。
有如下两种操作可以调整公布成绩的时间:

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

上面两种操作中的参数 \(X, Y, Z\) 均可任意指定,每种操作均可以执行多次,每次执行时都可以重新指定参数。
现在希望你通过合理的操作,使得最后总的不愉快度之和最小,输出最小的不愉快度之和即可。

Hint:

Solution:

很简单的一道题,容易发现只要答案只跟最后一门科目出的时间有关系

看到\(10^5\),果断直接枚举,处理好前缀和直接贪心就好

#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ls p<<1 
#define rs p<<1|1
using namespace std;
typedef unsigned long long ll;
const int mxn=1e5+5;
int n,m,cnt,hd[mxn];
ll t[mxn],b[mxn],bacb[mxn],bact[mxn],ans=1e17,A,B,C;

inline ll read() {
	char c=getchar(); ll x=0,f=1;
	while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
	while(c<='9'&&c>='0') {x=(x<<3)+(x<<1)+(c&15);c=getchar();}
	return x*f;
}
inline void chkmax(int &x,int y) {if(x<y) x=y;}
inline void chkmin(ll &x,ll y) {if(x>y) x=y;}

int main()
{
	A=read(); B=read(); C=read();
	n=read(); m=read();
	ll s1=0,s2=0,s3=0,t1=0,t2=0,t3=0;
	for(int i=1;i<=n;++i) t[i]=read(),++bact[t[i]],s3+=t[i],++t3;
	for(int i=1;i<=m;++i) b[i]=read(),++bacb[b[i]],s2+=b[i],++t2;
	for(int i=100000;i>=1;--i) {
		s1+=i*bacb[i],t1+=bacb[i];
		s2-=i*bacb[i],t2-=bacb[i];
		s3-=i*bact[i],t3-=bact[i];
		if(!s1) continue ; ll res=0,cnt1,cnt2;
		if(A<B) {
			cnt1=s1-t1*i,cnt2=t2*i-s2;
			res+=min(cnt1,cnt2)*A; cnt1-=min(cnt1,cnt2);
			if(cnt1) res+=cnt1*B;
		}
		else cnt1=s1-t1*i,res+=cnt1*B;
		res+=(t3*i-s3)*C; chkmin(ans,res);
	}
	printf("%lld",ans);
    return 0;
}

posted @ 2019-03-24 15:06  cloud_9  阅读(120)  评论(0编辑  收藏  举报