Minimizing Difference CodeForces - 1244E

You are given a sequence a1,a2,…,ana1,a2,…,an consisting of nn integers.

You may perform the following operation on this sequence: choose any element and either increase or decrease it by one.

Calculate the minimum possible difference between the maximum element and the minimum element in the sequence, if you can perform the aforementioned operation no more than kk times.

Input

The first line contains two integers nn and kk (2≤n≤105,1≤k≤1014)(2≤n≤105,1≤k≤1014) — the number of elements in the sequence and the maximum number of times you can perform the operation, respectively.

The second line contains a sequence of integers a1,a2,…,ana1,a2,…,an (1≤ai≤109)(1≤ai≤109) .

Output

Print the minimum possible difference between the maximum element and the minimum element in the sequence, if you can perform the aforementioned operation no more than kk times.

Examples

Input

4 5
3 1 7 5

Output

2

Input

3 10
100 100 100

Output

0

Input

10 9
4 5 5 7 5 4 5 2 4 3

Output

1

Note

In the first example you can increase the first element twice and decrease the third element twice, so the sequence becomes [3,3,5,5][3,3,5,5] , and the difference between maximum and minimum is 22 . You still can perform one operation after that, but it's useless since you can't make the answer less than 22 .

In the second example all elements are already equal, so you may get 00 as the answer even without applying any operations.

题意:给n个数,通过减一或者加一是最大最小相差的值最小,每加一或减一就是执行一次,要求不超过k次操作的最小差值。

 

思路:首先从小到大排序,进入while循环,同时从前和从后操作加一或者减一,记录整个数组变化的最小值mi和最大值ma;

两端要靠拢,每靠拢一次靠拢的一方以其所要改变的数的数量来作为判断依据,显然数量少才有可能靠拢的更为近一点。

当然不可以最大最小以加一或者减一的情况变化,因为10^9>=ai>=1,极端情况下就会遍历10^9次必然会超时,因为我就这样写

了一次。而按题上给的题意是给你的数的数量n<=10^5;所以通过数组中的数来变化就不会超时了。

 

代码如下:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
long long n,k,a[200200];
int main()
{
    while(~scanf("%lld %lld",&n,&k))
    {
        for(long long i=0; i<n; i++)
            scanf("%lld",&a[i]);
        sort(a,a+n);    //从大到小的排序
        long long mi=a[0],ma=a[n-1],num1=1,num2=1;//分别是现在的最小值、现在的最大值、现在从小往大要改变的数的数量、现在从大往小要改变的数的数量;
        long long l=1,r=n-2,d=0;//小->大、大->小:要变的下一个数的下标l和r;
        while(mi!=ma&&k)//判断条件满足最大==最小或者k==0时不再进行循环
        {
            long long x1=(a[l]-mi)*num1;//左向右靠拢需要加的次数
            long long x2=(ma-a[r])*num2;//右向左靠拢需要减的次数
            if(num1==num2)//当两端加一或者减一的数量相同时
            {
                if(k>=x1)//满足加到下一个数
                {
                    mi=a[l];//改变最小值
                    num1++;//左端最小值的数量
                    l++;//更新下一坐标
                    k-=x1;//减去执行的操作
                }
                else if(k>=x2)//满足可以减到前一个小的数,更新最大值,以及此时最大值的数量变化
                {
                    ma=a[r];
                    r--;
                    num2++;
                    k-=x2;
                }
                else//当都不满足时
                {
                    d=k/num1;//看最小能够加上或者最大能够减去的数也就是能达到最小最大数或者最大最小数
                    k=0;//显然不可能再满足了,k=0;
                }
            }
            else if(num1>num2)//下面两种就是挑需改变的数量最小的优先,因为这样差值会达到最小
            {
                if(k>=x2)
                {
                    ma=a[r];
                    r--;
                    num2++;
                    k-=x2;
                }
                else
                {
                    d=k/num2;
                    k=0;
                }
            }
            else
            {
                if(k>=x1)
                {
                    mi=a[l];
                    num1++;
                    l++;
                    k-=x1;
                }
                else
                {
                    d=k/num1;
                    k=0;
                }
            }
        }
        printf("%lld\n",ma-mi-d);
    }
    return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值