题目描述
南阳理工附属幼儿园有m个小胖友。每天,这些小胖友都要吃很多很多糖果,Miss.miao是负责分发糖果的老师,由于工作量巨大,Miss.miao经常不能保证每个小胖友分到的糖果数量是一样的。如果存在两个小胖友的糖果数量的差值超过k,那么这些小胖友就会很不开心。
现在,假设给出你每个小胖友的糖果数量,你作为这些小胖友中最聪明的一个,Miss.Miao老师要你协助她重新分配糖果,使得任意两个小胖友的糖果数量的差值不超过k。每一次,你可以将一个小胖友手里的一颗糖果拿给另外一个小胖友,但为了显示你的聪明才智,你必须用最少的次数完成任务。顽张ってください
输入
输入包含多组数据,每组包括两行,第一行两个数m,k,表示小胖友的数量和差值k(m<=1e6,k<=1e9)。
接下来一行m个正整数Ai,表示Miss.miao分给每个小胖友的糖果数量(Ai<=1e6)。
输出
对于每组数据,输出“Case #x: ans”,x表示当前是第几组数据,ans表示最少操作次数。
样例输入
3 1
1 2 3
4 3
1 5 1 10
Case #1: 1
Case #2: 4
很神奇,用桶排。
#include <stdio.h> #include <string.h> #define max(x,y) ((x)>(y)?(x):(y)) #define min(x,y) ((x)<(y)?(x):(y)) #define ll long long #define inf 0x3f3f3f3f #define maxn 1000005 int s[maxn]; int main() { ll sum; //此处应该使用long long int mn, mx; int m, k, x; int Case = 1; while(~scanf("%d %d",&m, &k)) { sum = 0; mx = -1; mn = inf; memset(s, 0, sizeof(s)); for(int i = 0; i < m; i++) { scanf("%d",&x); s[x]++; mx = max(mx, x); mn = min(mn, x); } while(mx - mn > k) { int t = min(s[mx], s[mn]); s[mx] -= t; s[mx-1] += t; s[mn] -= t; s[mn+1] += t; if(!s[mn]) mn++; //更新最值 if(!s[mx]) mx--; sum += t;//每次操作x个最值,分别把x个最小值+1,x个最大值-1 } printf("Case #%d: %lld\n",Case++, sum); } return 0; }