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])

(egin{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
",ans);
}