我太菜了,QAQ
Luogu
所有的见代码吧
#include<iostream> #include<cstdio> using namespace std; const int maxn=1e5+10; unsigned long long t[maxn],d[maxn],used[maxn]; unsigned long long c[maxn],up[maxn],n,m,A,B,C; //t[i]->时间上线为i的数目 unsigned long long flag,yes,last,x,ans; inline void prework(){ long long val=0,tot=0; if(flag!=3)//如果不是C大到离谱 for(register int i=1;i<=last;i++) val+=tot*C,tot+=t[i],c[i]=val; //统计C的结果看一看到i这个时间点不满值是多少 val=0;tot=0; for(register int i=1;i<=last;i++) val+=tot,tot+=d[i],used[i]=val; //看如果把时间线强行提到d[i],最多可以进行几次A val=0;tot=0; for(register int i=last;i>=1;i--) val+=tot,tot+=d[i],up[i]=val; //看如果把时间线强行提到d[i],最多要进行几次提升 } inline void work(){ //不用B的点 long long now;ans=c[last]; //如果一次提升也不进行,ans一直都是c[last] for(register int i=last;i>=1;i--){ now=c[i];//枚举最后一天 if(used[i]>=up[i]) now+=up[i]*A; //如果这个点要提升的次数大于最多可以用A提升的次数 //那你就无能为力了,所以此时直接退出 else break; ans>now?ans=now:ans=ans; } } inline void work1(){ ans=0ll;long long QAQ=0; //只用A,B的点,不能让学生等, //所以找到第一个有不满意值的时候,把所有的都提升到这个时候之前就好 for(register int i=1;i<=last;i++) if(t[i]){QAQ=i;break;}//首先找到一个需要提升的点 //即这个点有不满意值 if(yes)//如果B>A 就先用A if(used[QAQ]>=up[QAQ]) ans+=up[QAQ]*A; //如果A还可以再用一会儿 else ans+=used[QAQ]*A+(up[QAQ]-used[QAQ])*B; //当A用完了的时候,就只用B else ans+=up[QAQ]*B; //如果干脆A就B大,就只用B } inline void work2(){ //毫无特色的点 long long now;ans=c[last]; for(register int i=last;i>=1;i--){ now=c[i]; if(yes) if(used[i]>=up[i]) now+=up[i]*A; else now+=used[i]*A+(up[i]-used[i])*B; else now+=up[i]*B; ans>now?ans=now:ans=ans; } //毫无特色的注释 } int main(){ scanf("%llu%llu%llu%llu%llu",&A,&B,&C,&n,&m); for(register int i=1;i<=n;i++) scanf("%llu",&x),t[x]++; for(register int i=1;i<=m;i++) scanf("%llu",&x),last=max(x,last),d[x]++; if(B>A) yes=1; if(A==1e9&&B==1e9) flag=1; else if(A!=1e9&&B==1e9) flag=2; else if(C==1e16) flag=3; prework(); if(flag==1) printf("%llu",c[last]); else if(flag==2) work(); else if(flag==3) work1(); else work2();printf("%llu",ans); //毫无特色的主函数(除了压行) }