Опять зима-зима-зима-|

JosephusWang

园龄:2年7个月粉丝:3关注:4

[HAOI2008] 糖果传递

非常经典的数学题。

\(x_i\) 表示 \(i\) 给右边的人多少糖(如果 \(x_i<0\),就是从右边的人那里拿糖)。先考虑列出方程

\[\left\{\begin{matrix} a_1-x_1+x_n=\bar a \\ a_2-x_2+x_1=\bar a \\ \cdots \\ a_n-x_n+x_{n-1} =\bar a \\ \end{matrix}\right. \]

\(x_1\) 表示 \(x_2\)\(x_2=a_2+x_1-\bar a\)

\(x_2\) 表示 \(x_3\)\(x_3=a_3+x_2-\bar a\)

因此,用 \(x_1\) 表示 \(x_3\)\(x_3=a_3+a_2+x_1-\bar a-\bar a\)

类似的,可知

\[x_i=\sum_{j=2}^i (a_j-\bar a)+x_1\\ \]

换成减法,

\[x_i=x_1-\sum_{j=2}^i (\bar a-a_j) \]

题目要求最小化 \(\sum |x_i|\)。设 \(s_i=\sum_{j=2}^i (\bar a-a_j)\),即最小化

\[\sum_{i=1}^n |x_1-s_i| \]

这是一个经典的问题,当 \(x_1\)\(s\) 的中位数时原式最小。

// Title: 糖果传递
// Source: HAOI2008
// Author: Jerrywang
#include <bits/stdc++.h>
#define F first
#define S second
#define pii pair<int, int>
#define ll long long
#define rep(i, s, t) for(int i=s; i<=t; ++i)
#define debug(x) cerr<<#x<<":"<<x<<endl;
const int N=1000010;
using namespace std;
int n, a[N]; ll avg, res, s[N];
int main()
{
#ifdef Jerrywang
freopen("E:/OI/in.txt", "r", stdin);
#endif
scanf("%d", &n);
rep(i, 1, n) scanf("%d", a+i), avg+=a[i];
avg/=n;
rep(i, 2, n) s[i]=s[i-1]+avg-a[i];
sort(s+1, s+n+1);
int j=n/2+1; ll res=0;
rep(i, 1, n) res+=abs(s[j]-s[i]);
printf("%lld", res);
return 0;
}

本文作者:JosephusWang

本文链接:https://www.cnblogs.com/JosephusWang/p/18146838

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   JosephusWang  阅读(12)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起