AcWing 糖果傳遞
阿新 • • 發佈:2020-12-26
這題的詳解比較漫長,建議直接看<<指南>>.
這裡面的思維量還是不小的,猶如在做一道精巧的數學證明題,實際上這就是數學證明題.
我目前當然還沒有實力能夠獨立證明出這樣的結論.
簡化為模型記憶一下:
Q:有n人圍坐一圈,第i個人手中有a[i]張紙牌,現在他們需要在相鄰的人之間傳遞紙牌,相鄰的人傳遞一張紙牌的代價為1,求解使得最終所有人手中的紙牌數量相等所需要的最小代價.(假設資料有解,即a[i]之和為n的整數倍).
A:設a[i]之和即總紙牌數為T,將所有a[i]減去T / n,之後求a[i]字首和,設為s[i].
現在對s[i]進行排序以便取中位數s[(n + 1) / 2],計算出:
Σi=1nabs(s[i] - s[(n + 1) / 2])
即為答案.
程式碼倒是很短.
注意從在排序後的1~n個數中,中位數在第(n + 1) / 2個.
#include <algorithm> #include <cstdio> #include <cstring> #include <iostream> #include <cmath> using namespace std; int n, s[1000010]; long long t, ans; int main(){ scanf("%d", &n);for(int i = 1;i <= n; i++){ scanf("%d", s + i); t += s[i]; } for(int i = 1; i <= n; i++) s[i] += s[i - 1] - t / n; sort(s + 1, s + 1 + n); int mid = s[(n + 1) >> 1]; for(int i = 1; i <= n; i++) ans += abs(s[i] - mid); printf("%lld\n", ans);return 0; }