由於push和move這兩個操做,咱們比較容易發現這兩個操做好像在最大值最小值兩頭是等價的,所以當在最大最小值中間可能存在一個最優值,使操做成本最低。c++
經過上面的分析咱們能夠大體的獲得這是一個凹函數,而且存在最極小值,所以咱們能夠考慮三分去的到這個最小值。函數
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e5 + 10; int a[N], n, A, R, M; ll f(int x) { ll sum1 = 0, sum2 = 0;//分別記錄大於當前值的數量,和小於當前值的數量。 for(int i = 1; i <= n; i++) { if(a[i] > x) sum1 += a[i] - x; else if(a[i] < x) sum2 += x - a[i]; } ll ans = 0; ll mid = min(sum2, sum1); ans += mid * M; sum1 -= mid, sum2 -= mid;//優先考慮從一個移到另外一個上。 if(sum1) ans += sum1 * R; if(sum2) ans += sum2 * A; return ans; } int main() { // freopen("in.txt", "r", stdin); scanf("%d %d %d %d", &n, &A, &R, &M); M = min(M, A + R);//這個操做能夠等同是前兩個操做的和,取一個最小值。 for(int i = 1; i <= n; i++) scanf("%d", &a[i]); int l = 0, r = 1e9; while(l < r) { int lmid = l + (r - l) / 3; int rmid = r - (r - l) / 3; if(f(lmid) >= f(rmid)) l = lmid + 1; else r = rmid - 1; } printf("%lld\n", min(f(l), f(r))); return 0; }