1. 程式人生 > >CodeForces 671B Robin Hood

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;
}