【CF-1355 E.Restorer Distance】三分,贪心

E.Restorer Distance

题意

给出n相邻的个砖堆,有三种操作:

  1. 为一个砖堆添加一块砖,花费为A
  2. 从一个砖堆拿走一块砖,花费为R
  3. 从一个砖块上拿走一块砖放到另一个砖块上,花费为M

问将左右砖块的高度统一为一个值,最少花费为多少?

思路

首先(M=min(M,A+R))

假设最后的高度为(x),需要增加(L)块砖,需要减少(R)块砖,

那么我们先使用(min(L,R))次操作3。

剩下要么增加,要么减少。

花费是一个单峰函数,三分高度求解。

代码

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<vector>
#define pb push_back
typedef long long ll;
using namespace std;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const int N = 2e5+10;

ll h[N],n,a,r,m;
ll judge(ll x)
{
    ll low=0,high=0;
    for(ll i=1;i<=n;i++)
    {
        if(h[i]<=x) low+=x-h[i];
        else high+=h[i]-x;
    }
    ll minn=min(low,high);
    low-=minn,high-=minn;
    return a*low+r*high+m*minn;
}
int main()
{
    scanf("%lld%lld%lld%lld",&n,&a,&r,&m);
    m=min(m,a+r);
    for(ll i=1;i<=n;i++) scanf("%lld",&h[i]);
    ll tl=0,tr=1000000000;
    while(tl<tr)
    {
        ll m1=tl+(tr-tl)/3;
        ll m2=tr-(tr-tl)/3;
        if(judge(m1)>judge(m2)) tl=m1+1;
        else tr=m2-1;
    }
    printf("%lld
",judge(tl));
    return 0;
}
原文地址:https://www.cnblogs.com/valk3/p/12919610.html