P3051 [USACO12MAR]Haybale Restacking G

· · 题解

大意:

从原来的环形数列变成目标数列,对于所有物品,每移动一个单位,移动距离 x 花费为 x

求变换成目标序列的最小花费。

思考:

移动距离 = 花费,那就是相邻位置之间传递一单位物品,花费为1。

于是题意转化为:相邻位置间相互传递,使得原序列变成目标序列。求最小移动的数量总和

为糖果传递的一个变式题。

x_i 为最终从 i 位置传递到 i+1 位置的总干草数量。则:

目标数量 $=$ 该位置原数量 $-$ 传递到下一位置的总数量 $+$ 上一位置传递过来的总数量。 $B_1 = A_1 - x_1 + x_n$; $\Rightarrow$ $ x_1 = x_n + A_1 - B_1$; $B_2 = A_2 - x_2 + x_1$; $\Rightarrow$ $ x_2 = x_1 + A_2 - B_2 = x_n + A_1 + A_2 - B_1 - B_2$; $B_3 = A_3 - x_3 + x_2$; $\Rightarrow$ $ x_3 = x_2 + A_3 - B_3 = x_n + A_1 + A_2 + A_3 - B_1 - B_2 - B_3$; $... $\Rightarrow$ $ x_n = x_{n-1} + A_n - B_n = x_n + A_1 + A_2 +...+ A_n - B_1 - B_2 -...- B_n$; 要使移动的数量总和最小: 即 $x_1 + x_2 + x_3 + ... + x_n$ 最小,令 $C_i = B_i - A_i$,则: $|x_n - C_1| + |x_n - C_1 - C_2| + |x_n - C_1 - C_2 - C_3| + ... + |x_n - C1 - C_2 -...-C_n|$ 最小。 $C_i$ 维护前缀和 $S_i$,则使: $|x_n - S_1| + |x_n - S_2| + ...+ |x_n - S_n|$ 最小。 **绝对值不等式**,当 $x_n$ 为 $S_1,S_2...S_n$ 中位数的时候,总和最小。 --- ### Code: ``` #include<iostream> using namespace std; const int N=200010; int n,m,a[N], b[N], c[N]; int main(){ cin>>n; for(int i=1;i<=n;i++) cin>>a[i]>>b[i]; for(int i=1;i<=n;i++) c[i]=b[i]-a[i], c[i]+=c[i-1]; //差值、前缀 sort(c+1,c+n+1); int mid=c[n/2+1]; //取中位数 ll ans=0; for(int i=1;i<=n;i++) { ans+=abs(mid-c[i]); } cout<<ans; return 0; } ``` --- 三倍经验: [糖果传递](https://www.luogu.com.cn/problem/P2512)、 [士兵站队](https://www.luogu.com.cn/problem/P1889)。