【CF-1355 E.Restorer Distance】三分,贪心
E.Restorer Distance
题意
给出n相邻的个砖堆,有三种操作:
- 为一个砖堆添加一块砖,花费为A
- 从一个砖堆拿走一块砖,花费为R
- 从一个砖块上拿走一块砖放到另一个砖块上,花费为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\n",judge(tl));
return 0;
}