BZOJ_3969_[WF2013]Low Power_二分答案

时间:2022-02-15 05:05:29

BZOJ_3969_[WF2013]Low Power_二分答案

Description

有n个机器,每个机器有2个芯片,每个芯片可以放k个电池。
每个芯片能量是k个电池的能量的最小值。
两个芯片的能量之差越小,这个机器就工作的越好。
现在有2nk个电池,已知它们的能量,我们要把它们放在n个机器上的芯片上,
使得所有机器的能量之差的最大值最小。

Input

第一行,两个正整数,n和k。
第二行,2nk个整数,表示每个电池的能量。

Output

一行一个整数,表示所有机器的能量之差的最大值最小是多少。

Sample Input

2 3
1 2 3 4 5 6 7 8 9 10 11 12

Sample Output

1

HINT

2nk <= 10^6, 1 <= pi <= 10^9。

二分答案好题。
首先求最大值最小,能够想到二分答案$x$,然后看能不能塞进去即可。
把每个电池的能量从小到大排序,可以确定每个机器的两个芯片能量最好是相邻的两个数。
如果刚上来第一个和第二个之差就大于$x$了,显然不可以。
如果小于等于$x$,那么接下来可以放$2k$个电池,直到第$2k+1$的位置,如果相邻的差大于$x$就会导致不合法。
以此类推,记录一下之前有多少对数可以被选,有多少对就能使多少$2k$的位置合法。
 
代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <math.h>
using namespace std;
#define N 1000050
int a[N],n,k;
bool check(int x) {
int i,cnt=n;
for(i=1;cnt&&i<2*n*k;i++) {
if(a[i+1]-a[i]<=x) {
if(2*n*k-i+1<cnt*k*2) return 0;
i++;
cnt--;
}
}
return !cnt;
}
int main() {
scanf("%d%d",&n,&k);
int i,l=0,r=1000000001;
for(i=1;i<=2*n*k;i++) {
scanf("%d",&a[i]);
}
sort(a+1,a+2*n*k+1);
while(l<r) {
int mid=(l+r)>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
printf("%d\n",l);
}