1. 程式人生 > 實用技巧 >AcWing 糖果傳遞

AcWing 糖果傳遞

這題的詳解比較漫長,建議直接看<<指南>>.

這裡面的思維量還是不小的,猶如在做一道精巧的數學證明題,實際上這就是數學證明題.

我目前當然還沒有實力能夠獨立證明出這樣的結論.

簡化為模型記憶一下:

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; }