传送门:E - Restorer Distance 

题意:给出四个数 NA, 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 }