USACO 重排干草 Haybale Restacking, 2012 Mar

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 解释 将 6 捆干草从 1 号位移到 4 号位,1 捆干草 从 3 号位移到 2 号位,6 捆干草从 3 号位移到 4 号位

solution

设xi为第i堆干草与第i-1堆干草的交换数

令B[i]等于B[i]-A[i],则我们的目标是让B[i]全部变为0
B[1]-x1+x2=0 ==> x2=x1-B[1]
B[2]-x2+x3=0 ==> x3=x2-B[2]=x1-B[1]-B[2]
......xn-1=x1-B[1]-B[2]-...-B[n-1]
而我们要使 x1+x2+x3+...+xn-1 最小, 即|x1|+|x1-B[1]|+...+|x1-B[1]-B[2]-...-B[n-1]| 最小
所以x1要等于B[1],B[1]+B[2],...,B[1]+B[2]+...+B[n-1]的中位数

刘汝佳大神的蓝皮书第4页有道类似的题叫分金币,大佬们有兴趣可以看看

#include<cstdio>
#include<algorithm>
int N,M,B[100024];
long long Ans;
int main()
{
    scanf("%d", &N); M=(N+1)>>1;
    for(int a,g=1;g<=N;++g)
        scanf("%d%d", &a,&B[g]),B[g]-=a,B[g]+=B[g-1];
    std::sort(B+1,B+N+1);
    for(int g=1;g<=N;++g)
        Ans+=1ll*((B[g]>B[M])?B[g]-B[M]:B[M]-B[g]);
    printf("%lld", Ans);
    return 0;
}
原文地址:https://www.cnblogs.com/HollowM/p/7795111.html