Codeforces 672D Robin Hood

原创 2016年06月01日 09:53:41

题目链接:http://codeforces.com/problemset/problem/672/D


题意:对一个序列操作k次,每次将当前最大的数中分出去1给最小的数(如果有多个最大或最小随机选择,不过不影响答案)。求最后最大的数和最小的数的差值。


思路:k<=1e9 所以我们可以用二分法来做。现在我们假设操作k次后,最小的数为x。那么所有小于x的数都要加到x,t1 = ∑(x-a[i]) ( a[i] < x ),k至少要是这么多才可以;再考虑上界,如果操作很多,会把所有的x变成x+1或者更大,这样最小值就不是x了。所以我们记录所有小于等于x的数量t2,也就是说,当前最少操作t1次,这样所有小于x的数都会变成x,然后我们还可以最多再操作t2-1次,使得当前最小数还是x(再操作t2次,最小的数就会变成x+1)。二分求解最大的数同理。


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <utility>
using namespace std;

#define rep(i,j,k) for (int i=j;i<=k;i++)
#define Rrep(i,j,k) for (int i=j;i>=k;i--)

#define Clean(x,y) memset(x,y,sizeof(x))
#define LL long long
#define ULL unsigned long long
#define inf 0x7fffffff
#define mod %100000007
const int maxn = 500009;
LL n,k;
LL a[maxn];

void init()
{
    cin>>n>>k;
    rep(i,1,n) scanf("%I64d",&a[i]);
}

int check( LL x , int type )
{
    LL t1 = 0;
	LL t2 = 0;
	rep(i,1,n)
	if ( type == 0 )
    {
        if ( a[i] <= x )
        {
            t1 += x - a[i];
            t2++;
        }
    }
    else
    {
        if ( a[i] >= x )
        {
            t1 += a[i] - x;
            t2++;
        }
    }
	t2+=t1;
	if ( t1 > k ) return -1;
	if ( k >= t2 ) return 1;
	return 0;
}

void solve()
{
    LL S = 0;
    LL m1,m2;
    LL m,l,r;
    LL ml,mr;
    LL temp;
	ml = mr = a[1];

    rep(i,1,n)
    {
        S += a[i];
        if ( a[i] < ml ) ml = a[i];
        if ( a[i] > mr ) mr = a[i];
    }
    m1 = m2 = -1;
    l = ml;
    r = S/n;

    while( l < r )
    {
        m = ( l + r )>>1;
        temp = check(m , 0);
		if (temp == -1) r = m - 1;
		else if ( temp == 1 ) l = m + 1;
		else
		{
			m1 = m;
			break;
		}
    }
    if (m1==-1) m1 = l;

    l = (S+n-1)/n;
    r = mr;
    while( l < r )
    {
        m = ( l + r ) >> 1;
        temp = check(m , 1);
		if (temp == -1) l = m + 1;
		else if ( temp == 1 ) r = m - 1;
		else
		{
			m2 = m;
			break;
		}
    }
    if (m2==-1) m2 = l;
    printf("%I64d\n",m2-m1);
}
int main()
{
    init();
    solve();
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

【15.93%】【codeforces 672D】Robin Hood

time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard...

Codeforces 672D Robin Hood (二分)

题意有一个数列,有k天,每天可以让最大值减一最小值加一,求k天后最大值和最小值的差值。思路刚开始一直想着用什么东西维护一下,其实这个应该算是个模拟吧。 因为是把大的加到小的上面,所以我们只要看一下这...

Codeforces 672D Robin Hood【思维+二分】这题思路有点劲啊

D. Robin Hood time limit per test 1 second memory limit per test 256 megabytes input sta...

codeforces 672D Robin Hood (二分)

codeforces 672D Robin Hood (二分)

Codeforces #352 Div2 D Robin Hood(二分查找)

题目链接: Codeforces #352 Div2 D Robin Hood 题意: 给出n个数,每次可以将最大数-1,最小数+1,问K次后最大数和最小数之差? 分析: 二分查找k次最大数...

Codeforces 671B Robin Hood 二分答案

B. Robin Hood time limit per test 1 second memory limit per test 256 megabytes input standard ...

CodeForces Round 352——Recycling Bottles & Robin Hood

Recycling Bottles & Robin Hood

CodeForces 671B Robin Hood

 Description We all know the impressive story of Robin Hood. Robin Hood uses his archery ski...

【模拟】Codeforces 671B Robin Hood

题目链接:   http://codeforces.com/problemset/problem/671/B 题目大意:   N个人,每个人有Ci钱,现在有一个人劫富济贫,从最富...

Codeforces Round #352 (Div. 1) B. Robin Hood

We all know the impressive story of Robin Hood. Robin Hood uses his archery skills and his wits to s...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)