bzoj4868 [Shoi2017]期末考试(枚举+贪心)

直接枚举结束时间即可。两个指针来更新答案。
注意特判C==1e16的情况。

#include 
#include 
#include 
#include 
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(T==S){T=(S=buf)+fread(buf,1,1<<16,stdin);if(S==T) return EOF;}
    return *S++;
}
inline ll read(){
    ll x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
ll A,B,C,ans=1LL<<60;
int n,m,a[N],b[N];
int main(){
//  freopen("a.in","r",stdin);
    A=read();B=read();C=read();n=read();m=read();
    for(int i=1;i<=n;++i) a[i]=read();
    for(int i=1;i<=m;++i) b[i]=read();
    sort(a+1,a+n+1);sort(b+1,b+m+1);
    if(C==1e16){
        int x=a[1];ll s1=0,s2=0;
        for(int i=1;i<=m;++i)
            if(b[i]else s2+=b[i]-x;
        if(A>=B) ans=B*s2;
        else if(s1>=s2) ans=A*s2;
        else ans=A*s1+B*(s2-s1);printf("%lld\n",ans);return 0;
    }int p1=n,p2=m,c1=0,c2=0,c3=0;ll s1=0,s2=0,s3=0;
    for(int i=1;i<=n;++i) ++c3,s3+=a[i];
    for(int i=1;i<=m;++i) ++c1,s1+=b[i];
    for(int i=b[m];i>=a[1];--i){
        while(p1>=1&&a[p1]>=i) s3-=a[p1],--c3,--p1;
        ll a3=(ll)i*c3-s3,res=a3*C;
        while(p2>=1&&b[p2]>i) c2++,s2+=b[p2],c1--,s1-=b[p2],--p2;
        ll a2=s2-(ll)c2*i,a1=(ll)c1*i-s1;
        if(A>=B) res+=B*a2;
        else if(a1>=a2) res+=A*a2;
        else res+=A*a1+B*(a2-a1);ans=min(ans,res);
    }printf("%lld\n",ans);
    return 0;
}

你可能感兴趣的:(bzoj,贪心,暴力)