E. Restorer Distance 下凸型三分
题意:给出n个墙,每个墙有一定的高度,让我们把这些墙抹平(相同的高度)
给出三种操作,增加,删除,搬运(从高到低或者从低到高),各有各的权值
让我们计算,抹平的最小代价
思路:很显然,当答案趋于某个高度的时候,会得到最小代价,然后依次向两边改变高度的时候,
代价会越来越大(即下凸型)
思路明白之后,代码就很简单,如下
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=1e5+10; 5 ll h[maxn]; 6 ll n,a,r,m; 7 ll check(ll x) 8 { 9 ll suma=0,sumb=0; 10 for(int i=1;i<=n;i++){ 11 if(h[i]<=x){ 12 suma+=x-h[i]; 13 } 14 else sumb+=h[i]-x; 15 } 16 ll ans=0; 17 if(suma>=sumb){ 18 ans+=sumb*m; 19 suma-=sumb; 20 ans+=suma*a; 21 } 22 else{ 23 ans+=suma*m; 24 sumb-=suma; 25 ans+=sumb*r; 26 } 27 return ans; 28 } 29 int main() 30 { 31 scanf("%lld%lld%lld%lld",&n,&a,&r,&m); 32 if(a+r<=m) m=a+r; 33 for(int i=1;i<=n;i++){ 34 scanf("%lld",&h[i]); 35 } 36 ll L=0,R=1e9; 37 ll ans; 38 while(L<R){ 39 ll lmid=L+(R-L)/3; 40 ll rmid=R-(R-L)/3; 41 if(check(lmid)>check(rmid)){ //极大值求法 42 L=lmid+1; 43 // ans=check(midmid); 44 } 45 else{ 46 R=rmid-1; 47 // ans=check(mid); 48 } 49 } 50 ans=min(check(L),check(R)); 51 printf("%lld\n",ans); 52 return 0; 53 }