糖果传递(贪心,推公式)

题目链接:https://www.acwing.com/problem/content/124/

题目
n n n 个小朋友坐成一圈,每人有 a [ i ] a[i] a[i] 个糖果。

每人只能给左右两人传递糖果。

每人每次传递一个糖果代价为 1 1 1

求使所有人获得均等糖果的最小代价。

输入格式
第一行输入一个正整数 n n n,表示小朋友的个数。

接下来 n n n 行,每行一个整数 a [ i ] a[i] a[i],表示第 i i i 个小朋友初始得到的糖果的颗数。

输出格式
输出一个整数,表示最小代价。

数据范围
1 ≤ n ≤ 1000000 , 1≤n≤1000000, 1n1000000,
0 ≤ a [ i ] ≤ 2 × 1 0 9 , 0≤a[i]≤2×10^9, 0a[i]2×109,
数据保证一定有解。

输入样例:

4
1
2
5
4

输出样例:

4
思路:

在这里插入图片描述

如图所示(代价即交换次数)

假设 x i x_i xi表示 A i − 1 A_{i-1} Ai1传递到 A i A_i Ai的代价为 x i x_i xi
假设 − x i -x_i xi表示 A i A_{i} Ai传递到 A i − 1 A_{i-1} Ai1的代价为 x i x_i xi
则总代价为 ∣ x 1 ∣ + ∣ x 2 ∣ + . . . + ∣ x n ∣ |x_1|+|x_2|+...+|x_n| x1+x2+...+xn

下面研究每一个位置,平均数为avg
对于 A 1 A_1 A1,有 A 1 − x 1 + x n = a v g A_1-x_1+x_n=avg A1x1+xn=avg
对于 A 2 A_2 A2,有 A 2 − x 2 + x 1 = a v g A_2-x_2+x_1=avg A2x2+x1=avg
对于 A 3 A_3 A3,有 A 3 − x 3 + x 2 = a v g A_3-x_3+x_2=avg A3x3+x2=avg
. . . ... ...
对于 A n − 1 A_{n-1} An1,有 A n − 1 − x n − 1 + x n − 2 = a v g A_{n-1}-x_{n-1}+x_{n-2}=avg An1xn1+xn2=avg
对于 A n A_n An,有 A n − x n + x n − 1 = a v g A_n-x_n+x_{n-1}=avg Anxn+xn1=avg

移项可得
A 1 − a v g = x 1 − x n A_1-avg=x_1-x_n A1avg=x1xn
A 2 − a v g = x 2 − x 1 A_2-avg=x_2-x_1 A2avg=x2x1
A 3 − a v g = x 3 − x 2 A_3-avg=x_3-x_2 A3avg=x3x2
. . . ... ...
A n − 2 − a v g = x n − 2 − x n − 3 A_{n-2}-avg=x_{n-2}-x_{n-3} An2avg=xn2xn3
A n − 1 − a v g = x n − 1 − x n − 2 A_{n-1}-avg=x_{n-1}-x_{n-2} An1avg=xn1xn2
A n − a v g = x n − x n − 1 A_n-avg=x_n-x_{n-1} Anavg=xnxn1

把最后两项相加,有
A n + A n − 1 − 2 a v g − x n = − x n − 2 A_n+A_{n-1}-2avg-x_n=-x_{n-2} An+An12avgxn=xn2

把最后三项相加,有
A n + A n − 1 + A n − 2 − 3 a v g − x n = − x n − 3 A_n+A_{n-1}+A_{n-2}-3avg-x_n=-x_{n-3} An+An1+An23avgxn=xn3


0 − x n = − x n 0-x_n=-x_n 0xn=xn
A n − a v g − x n = − x n − 1 A_n-avg-x_n=-x_{n-1} Anavgxn=xn1
A n + A n − 1 − 2 a v g − x n = − x n − 2 A_n+A_{n-1}-2avg-x_n=-x_{n-2} An+An12avgxn=xn2
A n + A n − 1 + A n − 2 − 3 a v g − x n = − x n − 3 A_n+A_{n-1}+A_{n-2}-3avg-x_n=-x_{n-3} An+An1+An23avgxn=xn3
A n + A n − 1 + A n − 2 + A n − 3 − 4 a v g − x n = − x n − 4 A_n+A_{n-1}+A_{n-2}+A_{n-3}-4avg-x_n=-x_{n-4} An+An1+An2+An34avgxn=xn4
. . . ... ...
A n + A n − 1 + . . . + A 2 − ( n − 1 ) a v g − x n = − x 1 A_n+A_{n-1}+...+A_2-(n-1)avg-x_n=-x_1 An+An1+...+A2(n1)avgxn=x1


C 1 = A n − a v g C_1=A_n-avg C1=Anavg
C 2 = A n + A n − 1 − 2 a v g C_2=A_n+A_{n-1}-2avg C2=An+An12avg
C 3 = A n + A n − 1 + A n − 2 − 3 a v g C_3=A_n+A_{n-1}+A_{n-2}-3avg C3=An+An1+An23avg
. . . ... ...
C n − 1 = A n + A n − 1 + . . . + A 2 − ( n − 1 ) a v g C_{n-1}=A_n+A_{n-1}+...+A_2-(n-1)avg Cn1=An+An1+...+A2(n1)avg

则总代价可以表示为
∣ C 1 − x n ∣ + ∣ C 2 − x n ∣ + ∣ C 3 − x n ∣ + . . . + ∣ C n − 1 − x n ∣ + ∣ x n ∣ |C_1-x_n|+|C_2-x_n|+|C_3-x_n|+...+|C_{n-1}-x_n|+|x_n| C1xn+C2xn+C3xn+...+Cn1xn+xn

货仓选址可知,取中位数可以使不等式的值最小

另外 C i = C i − 1 + A i − a v g C_i=C_{i-1}+A_i-avg Ci=Ci1+Aiavg

AC代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

const int N = 1000010;

typedef long long LL;

int n;
LL arr[N],c[N];
LL all,avg,ans;

int main()
{
    scanf("%d",&n);
    for(int i = 0; i < n; i++)
    {
        scanf("%lld",&arr[i]);
        all += arr[i];
    }
    avg = all / n;
    c[0] = 0;
    // for(int i = 1; i < n; i++) c[i] = c[i-1] + avg - arr[i];
    // 上面这个递推式也行
    for(int i = 1; i < n; i++) c[i] = c[i-1] - avg + arr[i];
    sort(c,c+n);
    avg = c[n/2];
    for(int i = 0; i < n; i++) ans += abs(c[i] - avg);
    printf("%lld\n",ans);
    return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值