CodeForces 671B Robin Hood

B. Robin Hood

We all know the impressive story of Robin Hood. Robin Hood uses his archery skills and his wits to steal the money from rich, and return it to the poor.

There are n citizens in Kekoland, each person has ci coins. Each day, Robin Hood will take exactly 1 coin from the richest person in the city and he will give it to the poorest person (poorest person right after taking richest's 1 coin). In case the choice is not unique, he will select one among them at random. Sadly, Robin Hood is old and want to retire in k days. He decided to spend these last days with helping poor people. 

After taking his money are taken by Robin Hood richest person may become poorest person as well, and it might even happen that Robin Hood will give his money back. For example if all people have same number of coins, then next day they will have same number of coins too. 

Your task is to find the difference between richest and poorest persons wealth after k days. Note that the choosing at random among richest and poorest doesn't affect the answer.

Input

The first line of the input contains two integers n and k (1 ≤ n ≤ 500 000, 0 ≤ k ≤ 109) — the number of citizens in Kekoland and the number of days left till Robin Hood's retirement.

The second line contains n integers, the i-th of them is ci (1 ≤ ci ≤ 109) — initial wealth of the i-th person.

Output

Print a single line containing the difference between richest and poorest peoples wealth.

Examples

input

Copy

4 1
1 1 4 2

output

Copy

2

input

Copy

3 1
2 2 2

output

Copy

0

题目大意:Robin Hood每天将该镇最富裕的那个人的钱币给最穷的那个人,这样进行k天,当最穷的人和最富裕的人有相同的钱币时,Robin Hood将不再交换钱币。问第k天,该镇中最穷的人和最富的人金币差多少。

分析:稍微分析一下过程,我们发现这个结果算的是一个差值,而且这个差值是根据每一天在进行变化的,我们无法通过第k天的结果限制得到这个差值的限制条件。  因此我们无法直接对差值二分,我们需要通过二分其他变量来最终得到这个差值。由于 差值=富人-穷人,那么我们很自然的想到可以通过 二分得到第k天的最大值和最小值 最终得到差值,那么这个限制条件怎么确定呢。在这里我们不要去管中间的过程到底怎么样,我们只需要知道 若第k天的最大值是max 那么 对于第一天所给的镇上人财富的数据,比max大的人的钱币一定会被分走,而富人们要被分走的钱币数量的总和就是如果最大值为max 所需要的天数(因为分走一个钱币需要花费一天) ,同理可找到   最小值min和天数的关系,而这两个关系就是 二分的限定条件

下面上代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>

using namespace std;
typedef long long ll;

ll b[500005];
int n,k;//k次操作

int ok(int mx) {
    ll bigger = 0,smaller = 0;
    for(int i = 0; i < n; i++) {
        if(b[i] > mx) {//统计比当前答案大的富人的钱币总和
            bigger += (b[i]-mx);
        } else {//统计比当前答案小的穷人的钱币总和
            smaller += (mx-b[i]);
        }
    }
    if(bigger <= k && smaller >= bigger) return 1;//如果bigger小于天数,并且smaller大于多的,则我们向下二分,缩小最大值
    return 0;
}
int ok2(int mi) {
    ll smaller = 0,bigger = 0;
    for(int i = 0; i < n; i++) {
        if(b[i] < mi) {
            smaller += (mi-b[i]);//统计比当前答案小的穷人的钱币总和
        } else {
            bigger += (b[i]-mi);//统计比当前答案大的富人的钱币总和

        }
    }
    if(smaller <= k && bigger >= smaller) return 1;//若smaller小于天数,bigger大于小的总数,说明当前的答案太小,需要向上二分
    return 0;
}

int main() {
    scanf("%d%d",&n,&k);
    for(int i = 0; i < n; i++) {
        scanf("%I64d",&b[i]);
    }
    sort(b,b+n);
    int mx = b[n-1],mi = b[0];
    int high= mx,low = mi;
    while(low<= high) {
        int mid = (low+high)/2;
        if(ok(mid)) {
            high = mid-1;
            mx = mid;
        } else {
            low = mid+1;
        }
    }
    high = b[n-1];
    low = b[0];
    while(low<= high) {
        int mid = (low+high)/2;
        if(ok2(mid)) {
            low = mid+1;
            mi = mid;
        } else {
            high = mid-1;
        }
    }
    printf("%d\n",mx-mi);
    return  0;
}

猜你喜欢

转载自blog.csdn.net/xiao_you_you/article/details/81255258