BZOJ 4868 期末考试

Posted on 2017-11-03 15:10  ziliuziliu  阅读(76)  评论(0编辑  收藏

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;
}