CodeForces 614D Skills

排序+枚举+二分

最大的那些变成A,小的那部分提高最小值

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

const int maxn=100000+10;
int n;
long long A,cf,cm,m;
struct X
{
    long long a;
    long long ans;
    int id;
} s[maxn];
long long sum[maxn];

bool cmp1(const X&a,const X&b)
{
    return a.a<b.a;
}

bool cmp2(const X&a,const X&b)
{
    return a.id<b.id;
}

int main()
{
    scanf("%d%lld%lld%lld%lld",&n,&A,&cf,&cm,&m);
    for(int i=1; i<=n; i++)
    {
        scanf("%lld",&s[i].a);
        s[i].id=i;
        s[i].ans=s[i].a;
    }
    sort(s+1,s+1+n,cmp1);
    memset(sum,0,sizeof sum);
    for(int i=1; i<=n; i++) sum[i]=sum[i-1]+s[i].a;
    int ansPos1=0,ansPos2=0;
    long long Max=-1;
    long long ave=0;
    for(int i=0; i<=n; i++) //最后i个都变成A
    {
        long long cost=A*i-(sum[n]-sum[n-i]);//最后i个都变成A需要的费用
        if(cost>m) break;// 如果费用超过了m,则结束

        cost=m-cost;//剩余的费用
        int left=1,right=n-i;//二分查找的范围
        int pos=0;
        while(left<=right)
        {
            int mid=(left+right)/2;
            if(mid*s[mid].a-sum[mid]<=cost)
            {
                pos=mid;
                left=mid+1;
            }
            else right=mid-1;
        }
        long long q;
        if(pos!=0) q=min(A,(cost-pos*s[pos].a+sum[pos])/pos+s[pos].a);
        else q=A;
        if(q*cm+i*cf>Max)
        {
            Max=q*cm+i*cf;
            ansPos1=pos;
            ansPos2=i;
            ave=q;
        }
    }

    for(int i=n;i>=n-ansPos2+1;i--) s[i].ans=A;
    for(int i=1;i<=ansPos1;i++) s[i].ans=ave;

    printf("%lld
",Max);
    sort(s+1,s+n+1,cmp2);
    for(int i=1;i<=n;i++)
    {
        printf("%lld",s[i].ans);
        if(i<n) printf(" ");
        else printf("
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zufezzt/p/5141845.html