1. 程式人生 > >【BZOJ 1045】 [HAOI2008] 糖果傳遞

【BZOJ 1045】 [HAOI2008] 糖果傳遞

lac efi source span 遞推 所有 ret clu long

【鏈接】 我是鏈接,點我呀:)
【題意】


在這裏輸入題意

【題解】


思路來自hzwer..
設xi表示第i個人往左傳遞了xi個糖果。
(如果小於0表示旁邊的人給他了糖果。
則ans=∑|xi|
最後所有人的糖果數都變成sum/n->avg

a1-x1+x2 = avg
a2-x2+x3= avg
...

然後可以用avg和x1來表示所有的x2...xn
比如
x2 = x1-(avg-a1)
x3 = x1-(2avg-a1-a2)
....
會發現x1右邊的式子都是常量。
且都是x1-ci的形式

那麽就相當於有n個點。
然後現在讓你選擇一個點x1.
使得∑|x1-ci|最小。

顯然選擇所有這些點裏面的中位數就好。
(即ci的中位數
(ci可以觀察形式,用遞推的方法得到

【代碼】

#include <bits/stdc++.h>
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define all(x) x.begin(),x.end()
#define pb push_back
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1
using namespace std; const double pi = acos(-1); const int dx[4] = {0,0,1,-1}; const int dy[4] = {1,-1,0,0}; const int N = 1e6; int n; int a[N+10],c[N+10]; int main(){ #ifdef LOCAL_DEFINE freopen("rush_in.txt", "r", stdin); #endif scanf("%d",&n); rep1(i,1
,n) scanf("%d",&a[i]); LL sum = 0; rep1(i,1,n) sum+=a[i]; sum/=n; c[1] = sum-a[1]; rep1(i,2,n-1) c[i] = c[i-1] + sum-a[i]; c[n] = 0; sort(c+1,c+1+n); LL x1 = c[n/2+1]; sum = 0; rep1(i,1,n) sum+=abs(x1-c[i]); printf("%lld\n",sum); return 0; }

【BZOJ 1045】 [HAOI2008] 糖果傳遞