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); }