codeforces 671B Robin Hood 二分
2016-05-12 14:08
246 查看
题意:有n个人,每个人a[i]个物品,进行k次操作,每次都从最富有的人手里拿走一个物品给最穷的人
问k次操作以后,物品最多的人和物品最少的人相差几个物品
分析:如果次数足够多的话,最后的肯定在平均值上下,小的最多被补到sum/n,大最多减少到sum/n,或者sum/n+1
然后就二分最小值,看所有小的是否能在k次被填满
二分最大值,看所有大的是否都在k次被抹平
然后就是二分的写法,小和大的不一样,需要加等号,避免死循环
View Code
问k次操作以后,物品最多的人和物品最少的人相差几个物品
分析:如果次数足够多的话,最后的肯定在平均值上下,小的最多被补到sum/n,大最多减少到sum/n,或者sum/n+1
然后就二分最小值,看所有小的是否能在k次被填满
二分最大值,看所有大的是否都在k次被抹平
然后就是二分的写法,小和大的不一样,需要加等号,避免死循环
#include <stdio.h> #include <string.h> #include <algorithm> #include <math.h> using namespace std; typedef long long LL; const int N = 5e5+5; int a ,k,n; bool checkmax(int x){ int tmp=k; for(int i=1;i<=n;++i){ if(a[i]>x)tmp-=(a[i]-x); if(tmp<0)return false; } return true; } bool checkmin(int x){ int tmp=k; for(int i=1;i<=n;++i){ if(a[i]<x)tmp-=(x-a[i]); if(tmp<0)return false; } return true; } int main(){ scanf("%d%d",&n,&k); LL sum=0; int k1,k2,x=0,y=0x7f7f7f7f; for(int i=1;i<=n;++i){ scanf("%d",&a[i]); sum+=a[i]; x=max(x,a[i]); y=min(y,a[i]); } k1=k2=sum/n; if(sum%n)++k2; int ans2,ans1,l=y,r=k1; while(l<=r){ int m=(l+r)>>1; if(checkmin(m))ans1=m,l=m+1; else r=m-1; } l=k2,r=x; while(l<r){ int m=(l+r)>>1; if(checkmax(m))r=m; else l=m+1; } ans2=(l+r)>>1; printf("%d\n",ans2-ans1); return 0; }
View Code
相关文章推荐
- PHP扩展--opcache安装及配置
- PHP扩展--taint检测隐藏漏洞
- SQL生成周辅助表
- linux开机启动服务和chkconfig使用方法
- 剑指offer之面试题30最小的k个数
- 使用 spring 容器管理 Servlet
- adb shell
- adb shell
- adb shell
- adb shell
- 移动端H5知识普及[系列] - CSS3媒体查询
- [Servlet编程]Request,Response使用与码表原理
- 【SPOJ VLATTICE】Visible Lattice Points——莫比乌斯反演3
- sun.management.ManagementFactory is not visible
- jsp中target="_blank"的用法
- PHP扩展--vld查看opcode代码
- PHP扩展--XHProf优化PHP程序
- 我们是否需要RAC?
- call和apply的理解
- Mybatis SqlSessionTemplate 源码解析