O(n)做法大概是先推个不满意度的式子出来,然后维护一下调课和人的代价。
枚举时间,然后前缀和。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 100050 #define inf 0x7f7f7f7f7f7f7f7fLL using namespace std; long long aa,bb,cc,n,m,b[maxn],t[maxn],cnt1[maxn],cnt2[maxn],cnt3[maxn]; long long r1,r2,r3,ans=inf; long long read() { char ch;long long data=0; while (ch<'0' || ch>'9') ch=getchar(); while (ch>='0' && ch<='9') { data=data*10+ch-'0'; ch=getchar(); } return data; } int main() { aa=read();bb=read();cc=read(); n=read();m=read(); for (int i=1;i<=n;i++) {t[i]=read();cnt1[t[i]]++;} for (int i=1;i<=m;i++) {b[i]=read();cnt2[b[i]]++;cnt3[b[i]]++;} for (int i=1;i<=100000;i++) {cnt1[i]+=cnt1[i-1];cnt2[i]+=cnt2[i-1];} for (int i=100000;i>=1;i--) cnt3[i]+=cnt3[i+1]; long long T=100001; for (int i=1;i<=n;i++) r1+=max(T-t[i],(long long)0); for (int i=1;i<=m;i++) r2+=max(T-b[i],(long long)0); for (T=100000;T>=0;T--) { r1-=cnt1[T];r2-=cnt2[T];r3+=cnt3[T+1]; if ((long double)cc*r1>1e18) continue; if (bb<=aa) ans=min(ans,bb*r3+cc*r1); else if (r2>=r3) ans=min(ans,aa*r3+cc*r1); else ans=min(ans,aa*r2+bb*(r3-r2)+cc*r1); } printf("%lld\n",ans); return 0; }