题意:给出四个数 N, A, R, M ,然后给出一个长度为N的序列。让一个数+1花费A,-1花费R,从一个大的数向一个小的数移动1花费M。问让所有数一样大的最小花费。
题解:三分,每次找到可以移动的最大数量*M,再加上剩下比当前数小的*A,比当前数大的*R。
1 #include<bits/stdc++.h>
2 #define ll long long
3 using namespace std;
4
5 ll p[100100];
6 ll q[100100];
7 ll n,a,b,c;
8
9 ll check(ll sum)
10 {
11 ll ans=0,pp=0,qq=0;
12 for(ll i=1;i<=n;i++){
13 if(p[i]<sum) pp+=abs(p[i]-sum);
14 else qq+=p[i]-sum;
15 }
16 ans=min(pp,qq)*c+a*(pp-min(pp,qq))+b*(qq-min(pp,qq));
17 return ans;
18 }
19
20 int main()
21 {
22 ios::sync_with_stdio(false);
23 cin.tie(0);
24 cout.tie(0);
25 cin>>n>>a>>b>>c;
26 for(ll i=1;i<=n;i++) cin>>p[i];
27 sort(p+1,p+n+1);
28 c=min(a+b,c);
29 ll l=0,r=1e9;
30 for(ll i=0;i<100;i++){
31 ll mid=l+(r-l)/3;
32 ll mid2=r-(r-l)/3;
33 if(check(mid)<=check(mid2)){
34 r=mid2;
35 }
36 else l=mid;
37 }
38 ll ans=0x3f3f3f3f3f3f3f3f; //这个地方一定要开的足够大,不然会wa10
39 for(ll i=l;i<=r;i++) ans=min(ans,check(i));
40 cout<<ans<<endl;
41 return 0;
42 }