恩,非常好的题。。。至少思路非常巧妙
首先可以得到性质:对于相邻的两堆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 }
时间: 2024-10-12 12:43:05