E. Restorer Distance 高度平齐(三分)

题:https://codeforces.com/contest/1355/problem/E

题意:对于高度数组a[],目的是将所有高度平齐,有三种操作:1、a[i]--代价为R;2、a[i]++代价为A;3、将某一位置的一个单位转移到另一个位置 代价为M,问最小代价能平齐的高度;

分析:答案具有峰值性,即在极限的情况下,随着ans的减少,代价变多,随着ans增加,代价变多。那么这种情况就考虑三分!;

   因为操作三的贪心是min(M,A+R),所以check函数就是能补的就补,不能补的就靠操作1、2来弥补

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pb push_back
const int inf=0x3f3f3f3f;
const ll INF=1e18;
const int M=1e6+3;
const int mod=1e9+7;
ll ksm(ll x,ll y){
    ll t=1;
    while(y){
        if(y&1)
            t=(t*x)%mod;
        x=(x*x)%mod;
        y>>=1;
    }
    return t;
}
void pn(){
    cout<<"no"<<'\n';
}
void py(){
    cout<<"yes"<<'\n';
}
int nex[]={0,0,1,-1};
int ney[]={1,-1,0,0};
int n,A,R,minn;
int a[M];
ll check(int x){
    ll suma=0,sumb=0;
    for(int i=1;i<=n;i++){
        if(a[i]<x)
            suma+=x-a[i];
        if(a[i]>x)
            sumb+=a[i]-x;
    }
    ll tmp=min(suma,sumb);
    suma-=tmp,sumb-=tmp;
    return 1ll*suma*A+1ll*sumb*R+1ll*tmp*minn;
}
int main(){
    cin>>n>>A>>R>>minn;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    minn=min(minn,A+R);
    int l=0,r=inf,ans;
    while(l<r){
        int lmid=l+((r-l)/3);
        int rmid=r-((r-l)/3);
        if(check(lmid)<check(rmid))
            r=rmid-1;
        else
            l=lmid+1;
    }
    cout<<check(l)<<'\n';
    return 0;
}
View Code

 

posted @ 2020-05-17 10:44  starve_to_death  阅读(551)  评论(0编辑  收藏  举报