排序+枚举+二分
最大的那些变成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\n",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("\n"); } return 0; }
时间: 2024-11-11 06:03:15