codeforces 671B (二分) - xgtao -

题目链接

有n(<=500000)个人有各自的财富,Robin Hood要劫富济贫,每次把最富有的那个人的财富抢去1,加在最穷的那个人的财富里,但是一共只能抢有限次数,问最后最富有的那个人和最穷的那个人财富差的最小值。

要让最富有与最穷的差值最小,也就是要让一个最大值最小,最小值最大,用最大值最小-最小值最大那么就是最小,那么求这两个值就可以用二分.

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define LL long long
using namespace std;

const int maxn = 500010;
LL n,k,a[maxn],pre[maxn],sum,mini,maxi,ave;

int checkp(LL x) {
	int p = lower_bound(a+1,a+n+1,x)-a-1;
	if(p*x-pre[p] > k)return 0;//***
	else return 1;
}

int checkr(LL x) {
	int p = upper_bound(a+1,a+1+n,x)-a;
	if(pre[n]-pre[p-1]-(n-p+1)*x > k)return 0;//*****
	else return 1;
}

int main() {
	scanf("%I64d%I64d",&n,&k);
	for(int i = 1; i <= n; ++i)scanf("%I64d",&a[i]);
	sort(a+1,a+n+1);
	for(int i = 1; i <= n; ++i) {
		sum += a[i];
		pre[i] = pre[i-1]+a[i];
	}
	ave = sum / n;
	LL l = a[1],r = ave+1;
	while(l+1 < r) {
		LL mid = (l+r)/2;
		if(checkp(mid))l = mid;
		else r = mid;
	}
	mini = l;
	l = ave,r = a[n];if(sum%n)++l;
	while(l < r) {
		LL mid = (l+r)/2;
		if(checkr(mid))r = mid;
		else l = mid+1;
	}
	maxi = l;

	printf("%I64d\n",maxi-mini);
	return 0;
}

  

时间: 2024-09-28 16:31:15

codeforces 671B (二分) - xgtao -的相关文章

Codeforces 671B/Round #352(div.2) D.Robin Hood 二分

D. 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 wi

codeforces 671B Robin Hood 二分

题意:有n个人,每个人a[i]个物品,进行k次操作,每次都从最富有的人手里拿走一个物品给最穷的人 问k次操作以后,物品最多的人和物品最少的人相差几个物品 分析:如果次数足够多的话,最后的肯定在平均值上下,小的最多被补到sum/n,大最多减少到sum/n,或者sum/n+1 然后就二分最小值,看所有小的是否能在k次被填满 二分最大值,看所有大的是否都在k次被抹平 然后就是二分的写法,小和大的不一样,需要加等号,避免死循环 #include <stdio.h> #include <strin

CodeForces 801C 二分,浮点数

CodeForces 801C 题意: n个设备,第 i个设备每秒用电a[i],原本储存电量b[i].只有一个充电器,每秒可给一个设备充电 p.所有的设备要同时工作,问最多可以工作多长时间? tags:就是二分,但写挂了好多发.. 坑点: 1.右边界会爆1e9 ... 2.担心 double 会丢失精度,用了 long double. 然后long double ,头文件 #include <iomanip.h> .一开始用 printf("%.6Lf\n", r)输出,在

【模拟】Codeforces 671B Robin Hood

题目链接: http://codeforces.com/problemset/problem/671/B 题目大意: N个人,每个人有Ci钱,现在有一个人劫富济贫,从最富的人之一拿走1元,再给最穷的人.总共K次,问最后贫富差距. 钱被拿走是立刻结算,所以可能拿走后这个人变最穷的人再还回去. 最富或最穷的人可能有多个,随机选择,并且不会影响最终答案. (1 ≤ n ≤ 500 000, 0 ≤ k ≤ 109) 题目思路: [模拟] 直接排序离散化数据,之后模拟就行. 细节挺多的要处理清楚. 1

CodeForces 607A (二分)

/* ********************************************** CodeForces 607A Author:herongwei Created Time: 2016/5/31 13:00:00 File Name : main.cpp 一个线段上有n个灯塔,每个灯塔有两个属性 (位置和破坏距离) 现在一次性从右到左开启所有灯塔,每个灯塔开启后 只有该灯塔未被破坏时会破坏左边距离范围内所有灯塔, 问现在在最右边放置一个灯塔(位置和距离随意),所能破坏的最小灯塔

codeforces 359D 二分答案+RMQ

上学期刷过裸的RMQ模板题,不过那时候一直不理解>_< 其实RMQ很简单: 设f[i][j]表示从i开始的,长度为2^j的一段元素中的最小值or最大值 那么f[i][j]=min/max{d[i][j-1], d[i+2^j-1][j-1]} RMQ的ST算法: 1 void ST() //初始化 2 { 3 memset(RMQ,1,sizeof(RMQ)); 4 5 for(int i=1;i<=n;i++) 6 RMQ[i][0]=a[i]; 7 for(int j=1;(1<

Codeforces 825D 二分贪心

题意:给一个 s 串和 t 串, s 串中有若干问号,问如何填充问号使得 s 串中字母可以组成最多的 t 串.输出填充后的 s 串. 思路:想了下感觉直接怼有点麻烦,要分情况:先处理已经可以组成 t 串的部分,然后处理 s 串中可以利用的部分,如果还有问号剩余,再直接怼.但如果用二分写就很直观了,直接看最多能组成多少个 t 串. 居然踩了long long的坑感觉自己宛若一个zz.check函数中的计算要用long long防止溢出= =(明明大水题的说. #include<iostream>

Codeforces 460C 二分结果+线段树维护

发现最近碰到好多次二分结果的题目,上次多校也是,被我很机智的快速过了,这个思想确实非常不错.在正面求比较难处理的时候,二分结果再判断是否有效往往柳暗花明. 这个题目给定n个数字的序列,可以操作m次,每次要操作w个连续的数字,每次的操作将使得该段连续数字的数都+1,最后求整个序列最小值的最大值 求最小值最大,明显的二分结果的题目,我一开始还是在ACdream那个群里看到这个题,说是二分+线段树的题目,我就来做了一下..首先二分部分很容易,下界就是初始序列的最小值,上界就是 下界+m,至于怎么判断这

CodeForces 460C——二分+前缀和—— Present

Little beaver is a beginner programmer, so informatics is his favorite subject. Soon his informatics teacher is going to have a birthday and the beaver has decided to prepare a present for her. He planted n flowers in a row on his windowsill and star