Restorer Distance
思路
因为push和move这两个操作,我们比较容易发现这两个操作好像在最大值最小值两头是等价的,因此当在最大最小值中间可能存在一个最优值,使操作成本最低。
通过上面的分析我们可以大致的得到这是一个凹函数,并且存在最极小值,因此我们可以考虑三分去的到这个最小值。
代码
#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
", min(f(l), f(r)));
return 0;
}