BZOJ 4868 [Shoi2017] 期末考试

来源:互联网 发布:net java做什么用 编辑:程序博客网 时间:2024/06/07 01:00

Description

有n位同学,每位同学都参加了全部的m门课程的期末考试,都在焦急的等待成绩的公布。第i位同学希望在第ti天
或之前得知所.有.课程的成绩。如果在第ti天,有至少一门课程的成绩没有公布,他就会等待最后公布成绩的课程
公布成绩,每等待一天就会产生C不愉快度。对于第i门课程,按照原本的计划,会在第bi天公布成绩。有如下两种
操作可以调整公布成绩的时间:1.将负责课程X的部分老师调整到课程Y,调整之后公布课程X成绩的时间推迟一天
,公布课程Y成绩的时间提前一天;每次操作产生A不愉快度。2.增加一部分老师负责学科Z,这将导致学科Z的出成
绩时间提前一天;每次操作产生B不愉快度。上面两种操作中的参数X,Y,Z均可任意指定,每种操作均可以执行多次
,每次执行时都可以重新指定参数。现在希望你通过合理的操作,使得最后总的不愉快度之和最小,输出最小的不
愉快度之和即可

Input

第一行三个非负整数A,B,C,描述三种不愉快度,详见【问题描述】;
第二行两个正整数n,m(1≤n,m≤105),分别表示学生的数量和课程的数量;
第三行n个正整数ti,表示每个学生希望的公布成绩的时间;
第四行m个正整数bi,表示按照原本的计划,每门课程公布成绩的时间。
1<=N,M,Ti,Bi<=100000,0<=A,B,C<=100000

Output

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

Sample Input

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

Sample Output

6
由于调整操作产生的不愉快度太大,所以在本例中最好的方案是不进行调整; 全部
5 的门课程中,最慢的在第 3 天出成绩;
同学 1 希望在第 5 天或之前出成绩,所以不会产生不愉快度;
同学 2 希望在第 1 天或之前出成绩,产生的不愉快度为 (3 - 1) * 2 = 4;
同学 3 希望在第 2 天或之前出成绩,产生的不愉快度为 (3 - 2) * 2 = 2;
同学 4 希望在第 3 天或之前出成绩,所以不会产生不愉快度;
不愉快度之和为 4 + 2 = 6 。

HINT

 存在几组数据,使得C = 10 ^ 18

Source

黑吉辽沪冀晋六省联考

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

三分+贪心~

不忍直视……我在考场上写的暴力比正解长好多还挂掉了……智商是硬伤……

容易发现题目是一个二次函数,所以我们三分最后时间每次求出来生气值即可。

注意c==10^16时要特判,题目中写错了。


#include<cstdio>#include<iostream>using namespace std;#define ll long longll a,b,n,m,x[100001],y[100001],l,r;ll c;ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}while(ch>='0' && ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}ll cal(int u){ll ans=0;if(a<b){ll num1=0,num2=0;for(int i=1;i<=m;i++)  if(y[i]<=u) num1+=u-y[i];  else num2+=y[i]-u;if(num1>=num2) ans+=a*num2;else ans+=a*num1+b*(num2-num1);}else for(int i=1;i<=m;i++) ans+=max(0ll,y[i]-u)*b;for(int i=1;i<=n;i++) ans+=c*max(0ll,u-x[i]);return ans;}int main(){a=read();b=read();c=read();n=read();m=read();for(int i=1;i<=n;i++) x[i]=read();for(int i=1;i<=m;i++) y[i]=read();if(c==1e16){ll ans=999999999;for(int i=1;i<=n;i++) ans=min(ans,x[i]);printf("%lld\n",cal(ans)); return 0;}l=1;r=1e5;while(l+2<r){int mid1=(l*2+r)/3,mid2=(l+r*2)/3;ll ans1=cal(mid1),ans2=cal(mid2);if(ans1==ans2) l=mid1,r=mid2;else if(ans1<ans2) r=mid2;else l=mid1; }int mid1=(l+r*2)/3,mid2=(l*2+r)/3;printf("%lld\n",min(min(cal(l),cal(r)),min(cal(mid1),cal(mid2))));return 0;}


1 0
原创粉丝点击