USACO 重排干草&&BZOJ1045
USACO 重排干草&&BZOJ1045
Description
约翰订购了很多干草,他在农场里标记了 N 个位置。这些位置近似地构成一个圆环。他原打算 让送货司机在 i 号位卸下 Bi 捆干草。然而,送货司机搞乱了约翰的部署,胡乱卸货之后就离开了。 约翰数了数,目前在 i 号位有 Ai 捆干草,Ai 的总和是等于 Bi 的,说明司机至少没有少送货。
无奈之下,约翰只能自己来移动这些干草。约翰必须沿相邻位置来移动干草,每移动一捆干草到 一个相邻位置,要消耗约翰一单位的能量。请帮约翰规划一下,他最少消耗多少能量才能让所有位置 的干草数量从 {Ai} 变成 {Bi}?由于是圆环,所以 1 号位和 N 号位也算作是相邻的。
Input Format
• 第一行:单个整数 N ,1 ≤ N ≤ 10^5
• 第二行到 N + 1 行:第 i + 1 行有两个整数:Ai 和 Bi,1 ≤ Ai , Bi ≤ 1000
Output Format
单个整数:表示约翰消耗的最少能量之和
Sample Input
4
7 1
3 4
9 2
1 13
Sample Output
13
Hint
将 6 捆干草从 1 号位移到 4 号位,1 捆干草
从 3 号位移到 2 号位,6 捆干草从 3 号位移到 4号位
Solution
设\(p[i]\)表示\(i\)运往\(i-1\)的干草数量,\(p[1]\)表示\(1\)运往\(n\)的干草数量。
则有\(A[i]+p[i+1]-p[i]=B[i]\),设$C[i]=A[i]-B[i],Sum[i]=\sum _{j=1}^i C[i] $
\(p[i]=p[i-1]-C[i-1]\)
\(p[2]=p[1]-C[1]=p[1]-Sum[1]\)
\(p[3]=p[2]-C[2]=p[1]-C[1]-C[2]=p[1]-Sum[2]\)
\(\begin{array}{cc} &&&&&& \vdots \end{array}\)
$p[1]=p[1]-C[1]-C[2]- \cdots -C[n]=p[1]-Sum[n]=p[1] $
\(Ans=\sum |p[i]|=\sum |p[1]-Sum[i]|\)
显然要让答案最小让\(p[1]\)等于\(Sum\)的中位数即可。
BZOJ1045是这题的简化版。
Code
#include <cstdio>
#include <algorithm>
#define LL long long
inline int read(){
int num=0,k=1;char c=getchar();
while (c<'0'||c>'9'){if (c=='-')k=-1;c=getchar();}
while (c>='0'&&c<='9') num=(num<<1)+(num<<3)+c-48,c=getchar();
return num*k;
}
LL n,ans,c[100007];
int main(){
n=read();
for (int i=1;i<=n;++i) c[i]=read()-read()+c[i-1];
std::sort(c+1,c+n+1);
for (int i=1;i<=n;++i)
ans+=std::abs(c[i]-c[n>>1]);
printf("%lld\n",ans);
}