2415nyoj备用-吃糖果(模拟,桶排)

2415 : 吃糖果

题目描述
南阳理工附属幼儿园有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

(说是中档题,可是我这种小菜怎么能A。大佬们都太棒了!)

当最大的和最小的数相差不大于k,那么其他的就可能定不会大于k,所以拿糖果的时候,只需要减小最大值和最小值的差就好了。可是如果每次只变化一对最大最小值,肯定会超时,所以要桶排序,每次把最大值和最小值的一桶都给更新一下,就会减小更新次数。注意结果要用long long。


#include<map>
#include<set>
#include<queue>
#include<math.h>
#include<vector>
#include<string>
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#define inf 0x3f3f3f
#define ll long long
#define maxn 1000005
using namespace std;
int book[maxn];
int main(){
    int n,m,t=0;
    while(~scanf("%d%d",&n,&m)){
        int q1=-maxn,q2=maxn;
        memset(book,0,sizeof(book));
        for(int i=0;i<n;i++){int x;
            scanf("%d",&x);
            q1=max(q1,x);q2=min(q2,x);
            book[x]++;
        }
        ll ans=0;
        int big=q1,small=q2;
        while(big-small>m){
                int y=min(book[big],book[small]);//cout<<y<<endl;
                ans+=y;book[big]-=y;book[small]-=y;
                book[big-1]+=y;book[small+1]+=y;
                if(book[big]==0)big--;
                if(book[small]==0)small++;
        }
        printf("Case #%d: %lld\n",++t,ans);
    }
}


posted @ 2018-01-15 11:42  _大美  阅读(151)  评论(0编辑  收藏  举报