题目抽象一下:
分为两类:关于科目的不愉快度(A,B)和关于学生的不愉快度(C)
重点是想到二分 所有科目的结束时间。
对于超过结束时间的科目,如果B<=A,那么就尽量用B去更改时间,否则用A更改时间,不能再使用A了就再用B去更改。
而对于学生,小于时间界限i的还要产生C的不愉快度。
这样做所有情况都可以覆盖到。
然鹅这道题很容易爆LL啊。
#include<bits/stdc++.h> #define LL long long #define N 100003 #define INF 10000000000000000 using namespace std; LL read() { LL x=0,f=1;char s=getchar(); while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();} while(s>=‘0‘&&s<=‘9‘){x=x*10+s-‘0‘;s=getchar();} return x*f; } LL maxx=-1,minn=INF; int t[N],b[N]; int n,m; LL A,B,C; LL stu[N],ke[N]; LL k1=0,k2=0,s=0;//满足时间的科目,不满足时间的科目,满足时间的学生 个数 LL sum1=0,sum2=0,sum3=0;//满足时间的科目,不满足时间的科目,满足时间的学生 个数*时间 LL ans=INF; void work1() { LL res=0; for(int i=1;i<=n;++i) if((LL)t[i]<maxx)res+=(LL)(maxx-t[i])*(LL)C; printf("%lld\n",res); } void work2() { for(int i=100000;i>=1;--i) { LL res=0; sum1-=ke[i]*i;k1-=ke[i]; sum2+=ke[i]*i;k2+=ke[i]; sum3-=stu[i]*i;s-=stu[i]; if(i>minn)continue; if(!sum2)continue; if(A<B) { LL p=k1*i-sum1;//前面满足的 LL q=sum2-k2*i;//后面不满足的 res+=min(p,q)*A; q-=min(p,q); if(q)res+=q*B; } else { LL q=sum2-k2*i;//后面不满足的 res+=q*B; } ans=min(ans,res); } printf("%lld\n",ans); } int main() { freopen("exam.in","r",stdin); freopen("exam.out","w",stdout); A=read(),B=read(),C=read(); n=read(),m=read(); for(int i=1;i<=n;++i)t[i]=read(),stu[t[i]]++,s++,sum3+=t[i],minn=min(minn,(LL)t[i]); for(int i=1;i<=m;++i)b[i]=read(),ke[b[i]]++,k1++,sum1+=b[i],maxx=max(maxx,(LL)b[i]); if(A==1000000000&&B==1000000000&&C<=100){work1();return 0;} if(C==10000000000000000){work2();return 0;} sort(t+1,t+1+n);sort(b+1,b+1+m); for(int i=100000;i>=1;--i) { LL res=0; sum1-=ke[i]*i;k1-=ke[i]; sum2+=ke[i]*i;k2+=ke[i]; sum3-=stu[i]*i;s-=stu[i]; if(!sum2)continue; if(A<B) { LL p=k1*i-sum1;//前面满足的 LL q=sum2-k2*i;//后面不满足的 res+=min(p,q)*A; q-=min(p,q); if(q)res+=q*B; } else { LL q=sum2-k2*i;//后面不满足的 res+=q*B; } res+=(s*i-sum3)*C; ans=min(ans,res); } printf("%lld\n",ans); }
原文:https://www.cnblogs.com/yyys-/p/11544228.html