公元2411年,人类开始在地球以外的行星建立居住点。在第1326号殖民星上,N个居住点分布在一条直线上。为了方便描述,我们设第i个居住点的位置是Xi,其中居住着Yi位居民。随着冬季的到来,一些人口较多的居住点的生态循环系统已经开始超负荷运转。为了顺利度过严冬,殖民星上的居民一致同意通过转移到人口较少的居住点来减轻人口众多的居住点的负荷。
遗憾的是,1326殖民星的环境非常恶劣。在冬季到来前,每个居民点的居民最远能迁移到距离不超过R的居民点。1326殖民星的居民希望知道,如何安排迁移才能使完成迁移后人口最多的居民点人口最少?
注意有可能存在多个居民点位置相同。
输入:
第一行包含一个整数T(1 <= T <= 10),代表测试数据的组数。
每组数据的第一行包含2个整数N(1 <= N <= 100000)和R(0 <= R <= 10^9)。
以下N行每行包含两个整数,Xi和Yi(0 <= Xi, Yi, <= 10^9)。
输出:
对于每组数据输出迁移后人口最多的居民点人口最少可能的数目。
Sample Input
3
5 1
10 80
20 20
30 100
40 30
50 10
5 10
10 80
20 20
30 100
40 30
50 10
5 20
10 80
50 10
20 20
30 100
40 30
Sample Output
100
50
48
分析:
题目让求最大值的最小值,这样的问题一般来说就是二分,再加上答案有可能是在1e9的级别,那么就是二分的题目;
二分的题目关键就是如何判断解的大小;
对这一道题目来说:
1.我们假设i是当前位置,j是能够转移的位置;
2.再定义两个数组,分别是native[k],migration[k],分别表示居住点k可以移动的居民数,居住点k移民过来的居民数(不能再移动了,这些居民只能在居住点k);
3.然后利用贪心的方法,从左向右依次去让migration[j]=x(当然,要保证native[j]=0,但不一定是migration[j]=x的时候,native[j]=0),然后j+1,到下一个不满足migration=x的位置;
4.若最后的所有居住点的native存在大于0的情况,那么就是说明,当前的答案x太小了
#include <iostream>
#include <cmath>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#include <cstring>
#include <stack>
#include <string>
using namespace std;
typedef long long ll;
const int N = 1e5+199;
const double Pi = acos(-1);
int T,n;
struct node{
int xi;
ll yi;
bool operator < (const node &a) const{
return xi<a.xi;
}
}num[N];
ll migration[N],native[N],R;
bool Judge(ll x){
int i=0,j=0;
for(int i=0;i<n;i++) native[i]=num[i].yi,migration[i]=0;
while(i<n && j<n ){
if(abs(num[j].xi - num[i].xi) > R){
if(j>i) return false;
j++;
}
else{
if(native[i]+migration[j]<=x){
migration[j]+=native[i];
native[i]=0;
i++;
}else{
native[i]-=x-migration[j];
migration[j]=x;
j++;
}
}
}
for(int i=0;i<n;i++)
if(native[i]>0) return false;
return true;
}
ll Solve(ll lb,ll ub){
while(lb<=ub){
ll mid = (lb+ub)/2;
if(Judge(mid))
ub = mid - 1;
else
lb = mid + 1;
}
return lb - 1;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif // ONLINE_JUDGE
scanf("%d",&T);
while(T--){
scanf("%d%lld",&n,&R);
ll ub = 0;
for(int i=0;i<n;i++)
scanf("%d%lld",&num[i].xi,&num[i].yi),ub=max(ub,num[i].yi);
sort(num,num+n);
printf("%lld\n",Solve(0,ub));
}
return 0;
}