题解 P2512 【[HAOI2008]糖果传递】

C20203030

2019-10-21 21:38:22

Solution

## 一、题目 [点此看题](https://www.luogu.org/problem/P2512) ## 二、解法 设$x_i$为$i$号给$i-1$号$x_i$颗糖果(如果为负则方向相反),让后我们可以列出下面的式子: $a_1-x_1+x_2=ave$ $\dots \dots$ $a_i-x_i+x_{i+1}=ave$ 发现有$n-1$个方程,$n$个未知数,可以解出关系式(定义$c[i]=\sum_{j=1}^{i} a[j]-ave$): $x_i=x_1-c[i-1]$ 我们的答案就是$|x_1|+|x_1-c[1]|+...+|x_1-c[n-1]|$ 可以发现这就是个小学的邮局问题,取$c$的中位数即可。(说中位数可能有点不严谨,详细操作看代码吧) ```cpp #include <cstdio> #include <algorithm> using namespace std; #define int long long const int MAXN = 1000005; int read() { int x=0,flag=1;char c; while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1; while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar(); return x*flag; } int n,ave,ans,a[MAXN],s[MAXN]; int _abs(int x) { return x>0?x:-x; } signed main() { n=read(); for(int i=1;i<=n;i++) { a[i]=read(); ave+=a[i]; } ave/=n; for(int i=1;i<n;i++) s[i]=s[i-1]+a[i]-ave; sort(s+1,s+n); int x1=s[(n+1)/2],val=_abs(x1); for(int i=1;i<n;i++) ans+=_abs(x1-s[i]); n--; if(n%2==0) val=min(_abs(s[n/2]),_abs(s[n/2+1])); printf("%lld\n",ans+val); } ```