[六省联考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;
}

原文地址:https://www.cnblogs.com/list1/p/10588274.html