首页 > 代码库 > BZOJ2620 [Usaco2012 Mar]Haybale Restacking

BZOJ2620 [Usaco2012 Mar]Haybale Restacking

恩,非常好的题。。。至少思路非常巧妙

 

首先可以得到性质:对于相邻的两堆A & B,A给B然后B再给A是完全没有意义的。。。也就是说只能单向传递

然后我们记下每个点要给(被给)多少堆干草a[i]

同时可以计算出del[i],表示若第i堆只向右传且第n堆不向第1堆运任何干草的情况下i - 1向i传递干草的数量

del[i] = del[i - 1] + a[i - 1](其实就是前缀和)

现在1可以向右移了,设向右移x堆,则ans = Σabs(del[i] - x)

故x = mid(del + 1, del + n + 1)时,ans最小

更加详细见lrj白书P4。。。

 

 1 /************************************************************** 2     Problem: 2620 3     User: rausen 4     Language: C++ 5     Result: Accepted 6     Time:68 ms 7     Memory:1588 kb 8 ****************************************************************/ 9  10 #include <cstdio>11 #include <algorithm>12  13 using namespace std;14 typedef long long ll;15 const int N = 100005;16 int n;17 int a[N], del[N];18 ll ans;19  20 inline int read(){21     int x = 0, sgn = 1;22     char ch = getchar();23     while (ch < 0 || ch > 9){24         if (ch == -) sgn = -1;25         ch = getchar();26     }27     while (ch >= 0 && ch <= 9){28         x = x * 10 + ch - 0;29         ch = getchar();30     }31     return sgn * x;32 }33  34  35 int main(){36     n = read();37     int i, m = (n + 1) >> 1;38     for (i = 1; i <= n; ++i)39         a[i] = read(), a[i] -= read();40     for (i = 2; i <= n; ++i)41         del[i] = a[i - 1] + del[i - 1];42     del[1] = a[n] + del[n];43     sort(del + 1, del + n + 1);44     for (i = 1; i <= n; ++i)45         ans += abs(del[m] - del[i]);46     printf("%lld\n", ans);47     return 0;48 }
View Code

 

BZOJ2620 [Usaco2012 Mar]Haybale Restacking