Codeforces[1355E] Restorer Distance 【三分】

探讨了在给定条件下,通过三种操作使N堆砖块高度相等并最小化总成本的问题。采用三分法寻找最优高度,实现算法优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description 

You have to restore the wall. The wall consists of N pillars of bricks, the height of the ii-th pillar is initially equal to hihi, 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≤10^5, 0≤A,R,M≤10^4) — the number of pillars and the costs of operations. 

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

Ouput

 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

 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

题目大意:

给定N堆砖头,每堆砖有hi个,要求用以下三种操作使得所有堆的砖块个数相同(即高度相同),同时要使得花费最小。

1. 在一堆砖上加一块砖,花费为A;

2. 拿掉一堆砖顶上的一块砖,花费为R;

3. 将一块砖从一个堆顶移到另一个堆顶,花费为M;

分析:

 假设最终的高度为H,此时的花费最小。

考虑从H开始不断增加高度,那么就会有更多的hi小于H,必然会有更多的1操作,花费会增加;

同理,考虑从H开始不断降低高度,那么必然会有更多的2操作,花费会增加;

所以,可以看出答案是一个下凸函数。

下凸函数求极值,利用三分。

具体解释见代码。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <queue>
#define INF 0x3f3f3f3f
#define mst(a,num) memset(a,num,sizeof a)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define repd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef vector<int> VI;
const ll mod = 1e9 + 7;
const int maxn = 100000 + 5;
 
int h[maxn];
int n,a,r,m;
 
ll solve(int H){
    ll dwn=0,up=0;
    ll res=0;
    rep(i,1,n){
        if(h[i]<H){
            dwn+=0ll+H-h[i];
        }
        else{
            up+=0ll+h[i]-H;
        }
    }
    int mn=min(a+r,m);
    if(up>dwn){
        res+=1ll*dwn*mn;
        res+=1ll*(0ll+up-dwn)*r;
    }
    else{
        res+=1ll*up*mn;
        res+=1ll*(0ll+dwn-up)*a;
    }
    return res;
}
 
int main() {
    scanf("%d%d%d%d",&n,&a,&r,&m);
    int l=1e9,r=0;
    rep(i,1,n){
        scanf("%d",h+i);
        l=min(l,h[i]);
        r=max(r,h[i]);
    }
    int ansh=0;
    ll ans=1e18;
    while(l<=r){
        int lmid=l+(r-l)/3;
        int rmid=r-(r-l)/3;
        ll tmp1=solve(lmid);
        ll tmp2=solve(rmid);
        if(tmp1>tmp2){
            ansh=rmid;
            ans=tmp2;
            l=lmid+1;
        }
        else{
            ansh=lmid;
            ans=tmp1;
            r=rmid-1;
        }
    }
    // printf("%d\n",ansh);
    printf("%lld\n",ans);
    return 0;
}

 

### 解决方案概述 对于给定的问题,在一维坐标系中有 N 个点,每个点具有特定的权重 w。如果两个点之间的距离大于它们各自权重之和,则这两个点之间可以建立一条边。目标是从这些点中找到最大数量的点使得任意两点间均存在边。 为了实现这一目的,可以通过构建不等式 Xi-Wi ≥ Xj+Wj 来确定有向图中的节点关系[^3]。具体来说: - 对于每一对不同的点 (Xi, Wi) 和 (Xj, Wj),当 Xi > Xj 并且 Xi - Wi >= Xj + Wj 成立时,表示从 j 到 i 存在一个方向。 - Xj| >= Wi + Wj 的判断过程。 基于上述分析,算法设计如下: 1. 创建一个新的数组 P[],其中存储的是经过变换后的数据对 (Xi + Wi, Xi - Wi)。 2. 将此新创建的数据集按照第二个分量升序排列;如果有相同的情况,则按第一个分量降序处理。 3. 初始化计数器 count=0 及当前最小右端点 cur_min_right=-∞。 4. 遍历排序后的列表: - 如果当前元素的第一个分量大于等于cur_min_right,则更新count并设置新的cur_min_right为该元素的第二分量。 5. 输出最终的结果即为所求的最大团大小。 以下是 Python 实现代码示例: ```python def max_clique(n, points): # 计算转换后的点集合 [(xi+wi, xi-wi)] transformed_points = sorted([(points[i][0]+points[i][1], points[i][0]-points[i][1]) for i in range(n)], key=lambda x:(x[1], -x[0])) result = 0 current_end = float('-inf') for start, end in transformed_points: if start >= current_end: result += 1 current_end = end return result ``` 通过这种方法能够有效地解决问题,并获得最优解。值得注意的是,这里采用了一种贪心策略来逐步增加符合条件的顶点数目,从而保证了结果是最优的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值