Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 4847 Solved: 2436
[Submit][Status][Discuss]
Description
有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。
Input
第一行一个正整数nn<=1’000’000,表示小朋友的个数.
接下来n行,每行一个整数ai,表示第i个小朋友得到的糖果的颗数.
Output
求使所有人获得均等糖果的最小代价。
Sample Input
4
1
2
5
4
Sample Output
4
解题思路
此题跟均分纸牌很像,只是形成了一个环。所以如果直接枚举的时间复杂度是O(n^2),显然会T,所以找规律。sum[i]为a[i]-ave的前缀和。如果我们选取一点p为初始点,可以列出以下式子:
a[p] =sum[p]
a[p+1]=sum[p+1]-sum[p]
…
a[n]=sum[n]-sum[p]
a[1]=sim[1]-sum[p]
..
所以答案就为(sum[i]-sum[p]) 1<=i<=n (如果不知道的话去做做均分纸牌)
要使答案最小,当sum[p]为中位数时即可。
代码
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define LL long long using namespace std; const int MAXN = 1e6+5; inline int rd(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-48;ch=getchar();} return x*f; } int n,a[MAXN]; LL sum[MAXN],ave; LL ans; int main(){ n=rd(); for(register int i=1;i<=n;i++) a[i]=rd(),ave+=a[i]; ave/=n; for(register int i=1;i<=n;i++) a[i]-=ave,sum[i]=sum[i-1]+a[i]; sort(sum+1,sum+1+n); LL t=sum[(n+1)>>1]; for(register int i=1;i<=n;i++) ans+=abs(t-sum[i]); printf("%lld",ans); return 0; }