文章目录
- Question
- Ideas
- Code
Question
有 n 个小朋友坐成一圈,每人有 a[i] 个糖果。
每人只能给左右两人传递糖果。
每人每次传递一个糖果代价为 1。
求使所有人获得均等糖果的最小代价。
输入格式
第一行输入一个正整数 n,表示小朋友的个数。
接下来 n 行,每行一个整数 a[i],表示第 i 个小朋友初始得到的糖果的颗数。
输出格式
输出一个整数,表示最小代价。
数据范围
1≤n≤1000000,
0≤a[i]≤2×109,
数据保证一定有解。
输入样例:
4
1
2
5
4
输出样例:
4
Ideas
先求平均值,xi >0 代表 ai 给 ai-1 xi 个糖果 xi < 0 代表ai-1 给 ai xi 个糖果。(xi即为代价)
目标就是让所有的xi绝对值求和最小
给完糖果后 ai -xi+xi-1 = ave(平均值)
求解这个方程
可以用x1表示出所有的xi
最后得到一个|x-c| + |x-c|+ … |x-c| 形式的式子
让其最小,就是求x到各个c之间的距离最小
c排序后,x取中位数的时候目标式最小。
Code
# 贪心+线性代数 O(NlogN)
n = int(input())
a = [0 for i in range(n)]
for i in range(n):
a[i] = int(input())
# 求平均值
ave = sum(a) // n
# 求c
c = [0 for i in range(n)]
c[n-1] = ave - a[n-1] # Cn
for i in range(n-2,-1,-1):
c[i] = c[i+1] - ave + a[i+1] # 公式
# 在所有的c中找个x使得所有c到x的距离最小 ==> 排序 + 中位数
c.sort()
res = 0
mid = c[n//2] # 中位数
for i in c:
res += abs(i-mid)
print(res)