[bzoj1045][洛谷P2512][HAOI2008] 糖果傳遞
阿新 • • 發佈:2018-02-20
cst std using 中位數 ons 一行 ans logs 其中
,特殊地 \(l_1=r_n\)
設\(p\)為最終每個小朋友手中的糖果數
則有 \(l_i+a_i-r_i=p\) , 即 $ r_i=l_i+(a_i-p) $
而我們又有 \(l_i=r_{i-1}\)
一直遞歸下去有 $ r_i=l_1+(a_1-p)+(a_2-p)+(a_3-p)+…+(a_i-p) $
最終答案為 \(|r_1|+|r_2|+…+|r_n|\)
我們可以記下 \(a_i-p\) 的前綴和為 \(sum_i\)
那麽 \(ans=|l_1+sum_1|+|l_1+sum_2|+…+|l_1+sum_n|\)
絕對值是個美妙的東西,\(|l_1+sum_i|\) 可想為數軸上 \(-l_i\) 與 \(sum_i\) 的距離
那麽\(ans\)的最小值在 \(-l_1\) 取 \(sum_i\) 中位數時取到
Description
有n個小朋友坐成一圈,每人有ai個糖果。每人只能給左右兩人傳遞糖果。每人每次傳遞一個糖果代價為1。
Input
第一行一個正整數nn<=1‘000‘000,表示小朋友的個數.
接下來n行,每行一個整數ai,表示第i個小朋友得到的糖果的顆數.
Output
求使所有人獲得均等糖果的最小代價。
Sample Input
4
1
2
5
4
Sample Output
4
想法
設第\(i\)個小朋友從他左邊小朋友那裏得到 \(l_i\) 個糖果,向他右邊的小朋友傳遞 \(r_i\) 個糖果
(\(l_i\) 與 \(r_i\) 都可以為負數)
顯然 \(l_i=r_{i-1}\)
設\(p\)為最終每個小朋友手中的糖果數
則有 \(l_i+a_i-r_i=p\) , 即 $ r_i=l_i+(a_i-p) $
而我們又有 \(l_i=r_{i-1}\)
一直遞歸下去有 $ r_i=l_1+(a_1-p)+(a_2-p)+(a_3-p)+…+(a_i-p) $
最終答案為 \(|r_1|+|r_2|+…+|r_n|\)
我們可以記下 \(a_i-p\) 的前綴和為 \(sum_i\)
那麽 \(ans=|l_1+sum_1|+|l_1+sum_2|+…+|l_1+sum_n|\)
絕對值是個美妙的東西,\(|l_1+sum_i|\) 可想為數軸上 \(-l_i\)
那麽\(ans\)的最小值在 \(-l_1\) 取 \(sum_i\) 中位數時取到
求出\(sum_i\)及其中位數後計算即可。
代碼
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N = 1000005; int a[N]; ll sum[N],p; int n; int main() { scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); p+=a[i]; } p=p/n; sum[0]=0; for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i]-p; sort(sum+1,sum+1+n); ll l=sum[n/2+1],ans=0; //註意:中位數為n/2+1而不是n/2 for(int i=1;i<=n;i++) ans+=abs(sum[i]-l); printf("%lld\n",ans); return 0; }
[bzoj1045][洛谷P2512][HAOI2008] 糖果傳遞