题解P3745期末考试

送分小仙女□ 提交于 2019-11-30 13:36:22
我太菜了,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);
    //毫无特色的主函数(除了压行)
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!