推公式
对于每一个小孩,得到或者是拿出只可能是来自相邻小孩
所以对于每一个小孩的贡献度我们可以算出来
xi: 第i个小孩给 xi 个糖果给 i-1位小孩
ave : 平均值
推倒过程如下:
ans = |x1|+...+|xn|;
a1 - x1 + x2 = ave;
令 c1 = a1 - ave;
=> x2 = x1 - c1;
同理
a2 - x2 + x3 = ave;
=> x3 = x2 - (a2-ave) = x1 - c1 - (a2 - ave) = x1 - (c1+(a2 - ave));
令 c2 = a2 - ave + c1;
同理 x3 .... xn
现在就转化为求
|x1| + |x1-c1| + |x1 - c2|+....+ |x1-cn-1| 的最小值
每个c可以求得
那么x1 其实就是中位数,这个问题就求解了
代码如下:
/* ^^ ====== ^^
ID: meixiuxiu
PROG: test
LANG: C++11
*/
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <climits>
#include <string>
#include <vector>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <sstream>
#include <cctype>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int ,int> pii;
#define MEM(a,b) memset(a,b,sizeof a)
#define CLR(a) memset(a,0,sizeof a);
#define pi acos(-1.0)
#define maxn 40000
#define maxv 100005
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
//#define LOCAL
int a[1000000];
ll b[1000000];
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
int n;cin >> n;
int i;
for(i=1;i<=n;i++)scanf("%d",&a[i]);
ll sum = 0;
for(i=1;i<=n;i++){
sum += a[i];
}
ll ave = sum/n;
b[1] = 0;
for(i=2;i<=n;i++){
b[i] = b[i-1] + a[i-1]-ave;
}
sort(b+1,b+1+n);
ll mid;
if(n&2){
mid = b[n/2+1];
}
else mid = (b[n/2]+b[n/2+1])/2;
ll tot = 0;
for(i=1;i<=n;i++){
tot += fabs(mid-b[i]);
}
printf("%lld\n",tot);
return 0;
}