CF1355E Restorer Distance(三分)

/*
 * CF1355E
 * 题意:
 * 给你一个长度为n的数组,你可以向一个元素加1,代价为A,也可以向一个元素减1,代价为R,
 * 还可以把一个元素的1移动到另外一个元素上,代价为M。
 * 现在要求你做一些操作,使得所有元素高度相等。
 * 题解:
 * 根据题意,合法答案应该在最小值和最大值之间。两端的费用应该是大于答案。
 * 可以看到,这是一个单峰函数,可以用三分查找解决。
 */
#include<bits/stdc++.h>
 
using namespace std;
typedef long long ll;
const int maxn=1e6+100;
int n;
ll a[maxn];
int A,R,M;
ll check (int mid) {
    ll ans=0;
    ll t1=0;
    ll t2=0;
    if (A+R<=M) {
        for (int i=1;i<=n;i++) {
            if (a[i]<mid)
                ans+=(mid-a[i])*A;
            else
                ans+=(a[i]-mid)*R;
        }
    }
    else {
        for (int i=1;i<=n;i++) {
            if (a[i]<mid)
                t1+=(mid-a[i]);
            if (a[i]>mid)
                t2+=(a[i]-mid);
        }
        ll Min=min(t1,t2);
        ans+=Min*M;
        t1-=Min;
        t2-=Min;
        ans+=t1*A+t2*R;
    }
    return ans;
}
 
 
int main () {
    scanf("%d%d%d%d",&n,&A,&R,&M);
    for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
    ll l=0;
    ll r=1e9;
    while (l+20<r) {
        ll mid=l+(r-l)/3;
        ll mmid=mid+(r-l)/3;
        if (check(mid)>check(mmid))
            l=mid;
        else
            r=mmid;
    }
    ll ans=1e18;
    for (int i=l;i<=r;i++)
        ans=min(ans,check(i));
    printf("%lld\n",ans);
}

猜你喜欢

转载自www.cnblogs.com/zhanglichen/p/12952261.html