这道题思路很巧妙,首先需要知道一个结论,|x-c1|+|x-c2|+|x-c3|...即x到c1,c2,c3...各个点的距离之和,要取最小值的话,那么x就取c1,c2...的中位数,具体证明上面一张图有。
因为是环形座位,每个人可以把自己的金币可以给左边和右边的人,为了方便表示,用xi来表示第i个人将xi个金币分给左边的人,这样如果某人给右边的人5个金币,那就等价于右边的人给他-5个金币,这样的处理方式很重要。
然后x1最后的金币数=他本来有的-x1+x2,方程只有x1,x2 2个变量,所以就得到了x1,x2的关系,可以用x1表示出x2,同理,x3和x2也有类似关系,所以可以用x1表示出所有xi,因为最终结果是要求|x1|+|x2|+|x3|...的最小值,就转换为|x-c1|+|x-c2|+|x-c3|...
#include <cstdio>
#include <algorithm>
#include <cmath>
#define MAXN 1000010
using namespace std;
typedef long long ll;
ll a[MAXN],point[MAXN];
ll n;
int main() {
while (scanf("%d",&n) != EOF) {
ll cnt = 0;
for(int i = 0;i < n;i++) {
scanf("%lld",&a[i]);
cnt += a[i];
}
ll m = cnt / n;
ll tempA = 0;
for(int i = 0;i < n;i++) {
tempA += a[i];
point[i] = tempA - (i+1)*m;
}
sort(point,point+n);
ll temp = point[n/2];
ll result = 0;
for(int i = 0;i < n;i++)
if(point[i] >= temp)
result += point[i] - temp;
else
result += temp - point[i];
printf("%lld\n",result);
}
return 0;
}