Codeforces Round #643 1355E.Restorer Distance(三分/二分)

题目描述:

E. Restorer Distance

time limit per test 1 second

memory limit per test 256 megabytes

You have to restore the wall. The wall consists of N pillars of bricks, the height of the i-th pillar is initially equal to hi, the height is measured in number of bricks. After the restoration all the N pillars should have equal heights.

You are allowed the following operations:

put a brick on top of one pillar, the cost of this operation is A;
remove a brick from the top of one non-empty pillar, the cost of this operation is R;
move a brick from the top of one non-empty pillar to the top of another pillar, the cost of this operation is M.
You cannot create additional pillars or ignore some of pre-existing pillars even if their height becomes 0.

What is the minimal total cost of restoration, in other words, what is the minimal total cost to make all the pillars of equal height?

Input
The first line of input contains four integers N, A, R, M (1≤N≤105, 0≤A,R,M≤104) — the number of pillars and the costs of operations.

The second line contains N integers hi (0≤hi≤109) — initial heights of pillars.

Output
Print one integer — the minimal cost of restoration.

Examples
input

3 1 100 100
1 3 8

output

12

input

3 100 1 100
1 3 8

output

9

input

3 100 100 1
1 3 8

output

4

input

5 1 2 4
5 5 3 6 5

output

4

input

5 1 2 2
5 5 3 6 5

output

3

算法标签:三分/二分

题目大意:对于n堆石头,每堆高度为 h i h_i hi,可以做三种操作:

  1. 使某堆石头高度+1,代价为A
  2. 使某堆石头高度-1,代价为R
  3. 将一块石头从一堆搬到另一堆(一堆高度-1,另一堆高度+1),代价为M

问使得每堆石头的高度都相同的最小代价。

首先,如果 A + R < = M A+R<=M A+R<=M,意味着搬石头的代价大于先加一块再减一块,因此直接令 M = m i n ( M , A + B ) M=min(M,A+B) M=min(M,A+B)

假设给定最终石堆的高度为H,计算出总共需要增加的石头数 u p up up,以及减去的石头数 d o w n down down(朴素思想复杂度为O(n)),分情况考虑up和down的大小关系,可以直接计算出总代价
c = { ( d o w n − u p ) ∗ R + u p ∗ M ( d o w n > = u p ) ( u p − d o w n ) ∗ A + d o w n ∗ M ( d o w n < u p ) c=\left\{ \begin{aligned} (down-up)*R+up*M & &{(down>=up)} \\ (up-down)*A+down*M & &{(down<up)} \end{aligned} \right. c={(downup)R+upM(updown)A+downM(down>=up)(down<up)

那么只要确定H与c的关系是一个存在最小值,且在最小值左、右侧分别具有单调性(类似于单谷函数),就可以用三分(或者二分判断增量)找到最小代价了,问题就在于怎么证明它有类似于单谷函数的单调性。

contest的时候当然凭感觉猜一下,或者通过打表之类的方法观察到了就可以直接开始写了,但是回过头看似乎很难想到一个直观且严谨的证明方法,所以这里就只能通过比较麻烦的数学计算来证明一下。

H ′ = H + Δ H H'=H+\Delta H H=H+ΔH c ′ = c + Δ c c'=c+\Delta c c=c+Δc。我们来考虑当 Δ H = 1 \Delta H=1 ΔH=1时,c的增量 Δ c \Delta c Δc。只要能证明 Δ c \Delta c Δc在整个过程中是单调不递减的,就能证明 c c c符合要求。

令高度小于 H ′ H' H的石堆个数为 X X X,那么 u p ′ = u p + X , d o w n ′ = d o w n − ( n − X ) = d o w n + X − n up'=up+X,down'=down-(n-X)=down+X-n up=up+X,down=down(nX)=down+Xn
为了计算 Δ c \Delta c Δc,我们先考虑 d o w n > = u p down>=up down>=up d o w n ′ > = u p ′ down'>=up' down>=up的情况。
Δ c = c ′ − c = ( d o w n ′ − u p ′ ) ∗ R + u p ′ ∗ M − ( d o w n − u p ) ∗ R − u p ∗ M \Delta c=c'-c=(down'-up')*R+up'*M-(down-up)*R-up*M Δc=cc=(downup)R+upM(downup)RupM代入后计算得到 Δ c = X ∗ M − R ∗ n \Delta c=X*M-R*n Δc=XMRn
同理,当 d o w n < u p down<up down<up Δ c = X ∗ M − ( M − A ) ∗ n \Delta c=X*M-(M-A)*n Δc=XM(MA)n
也就是
Δ c = { X ∗ M − R ∗ n d o w n > = u p X ∗ M − ( M − A ) ∗ n d o w n < u p \Delta c=\left\{ \begin{aligned} X*M-R*n & &{down>=up}\\ X*M-(M-A)*n & &{down<up} \end{aligned} \right. Δc={XMRnXM(MA)ndown>=updown<up
又因为 M = m i n ( M , A + R ) M=min(M,A+R) M=min(M,A+R),所以 ( M − A ) < = R (M-A)<=R (MA)<=R,当down<up时, Δ c > = X ∗ M − R ∗ n \Delta c>=X*M-R*n Δc>=XMRn
于是 Δ c \Delta c Δc X X X的如图红线(断开来的地方就是down和up关系变化的点),满足单调不递减
在这里插入图片描述
然后问题在于证到这里现在只能说明 Δ c \Delta c Δc在两段上各自单调不递减,没有考虑到由down>=up变为down<up的那一次变化的增量。所以我们再把这种情况单独拿出来。

此时 c c c用down>=up的情形计算,而 c ′ c' c用down<up的情形计算,得到
Δ c = X ∗ M − ( A + R − M ) ∗ ( d o w n − u p ) − n ∗ ( M − A ) \Delta c=X*M-(A+R-M)*(down-up)-n*(M-A) Δc=XM(A+RM)(downup)n(MA)
我们需要证的是,

  1. Δ c < 0 \Delta c<0 Δc<0 X ∗ M − n ∗ R < = 0 X*M-n*R<=0 XMnR<=0也成立(上一次变化也要<=0);
  2. Δ c > 0 \Delta c>0 Δc>0 X ∗ M − ( M − A ) ∗ n > = 0 X*M-(M-A)*n>=0 XM(MA)n>=0也成立(下一次变化也要>=0)

(这里不要求 Δ c \Delta c Δc的单调性了,而只考虑它的正负)
(如果 Δ c = 0 \Delta c=0 Δc=0,c变化量为0,总是符合要求,不作考虑)
证明:

  1. d o w n − u p < = n down-up<=n downup<=n(否则 d o w n ′ < u p ′ down'<up' down<up不成立)得,
    X ∗ M − n ∗ R = X ∗ M − ( A + R − M ) ∗ n − n ∗ ( M − A ) < = Δ c < 0 X*M-n*R=X*M-(A+R-M)*n-n*(M-A)<=\Delta c<0 XMnR=XM(A+RM)nn(MA)<=Δc<0

  2. A + R − M > = 0 , d o w n − u p > = 0 A+R-M>=0,down-up>=0 A+RM>=0downup>=0 ( A + R − M ) ∗ ( d o w n − u p ) > = 0 (A+R-M)*(down-up)>=0 (A+RM)(downup)>=0
    因此 0 < Δ c < = X ∗ M − ( M − A ) ∗ n 0<\Delta c<=X*M-(M-A)*n 0<Δc<=XM(MA)n

由以上两点,c在从 d o w n > = u p down>=up down>=up d o w n < u p down<up down<up 这一步的变化中也能够维护极值两侧的单调性了。

这种证法可能看上去比较吃力,但是至少逻辑上说得通了。希望以后能找到别的更好的理解方法吧。

有了这个之后就符合三分或者二分的条件了。

贴一个二分高度判断增量+二分求代价的代码,复杂度 O(logNlogN),(但是跟O(N)求代价的O(NlogN)算法跑下来时间差不多)通过判断当前位置mid和mid+1所需代价的关系,即可确定mid在极值左侧还是极值右侧。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
 
const int N=2e5+5;
int n,a,r,m,mid;
ll sum[N],h[N];
 
ll cal(ll x)
{
    ll down=0,up=0,ret=0;
    int pos=lower_bound(h+1,h+1+n,x)-h;
    if (pos>=1)up+=(pos-1)*x-sum[pos-1];
    if (pos<=n)down+=(sum[n]-sum[pos-1])-(n-pos+1)*x;
    if (up>down) ret+=(up-down)*a,up=down;
    else
        ret+=(down-up)*r,down=up;
    ret+=up*min(a+r,m);
    return ret;
}
int main()
{
    cin>>n>>a>>r>>m;
    for (int i=1;i<=n;i++)
        scanf("%lld",&h[i]);
    sort(h+1,h+1+n);
    for (int i=1;i<=n;i++)
        sum[i]=sum[i-1]+h[i];
    int l=0,r=1e9;
    while(r-l>1)
    {
        mid=(l+r)>>1;
        if (cal(mid)>cal(mid+1))
            l=mid;
        else
            r=mid;
    }
    printf("%lld",min(cal(l),cal(r)));
    return 0;
}
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值