2>居民迁移问题
题目链接:http://hihocoder.com/problemset/problem/1053
时间限制:
3000ms
单点时限:
1000ms
内存限制:
256MB
描述
公元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)。
输出
对于每组数据输出迁移后人口最多的居民点人口最少可能的数目。
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样例输出
100 50 48
采用二分搜索策略,结合贪心思想,尽可能的往左边安排居民。
#include<iostream>
#include<time.h>
#include<algorithm>
#include<vector>
using namespace std;
struct node
{
int x,y, label,leftIndex;
};
bool cmp(node a, node b)
{
return a.x < b.x;
}
//双线性方法 两个数组,一个待填充,一个作为填充源,填充后,只要填充源中还有没有被填充的,则验证结果为不可以
int testNum3(vector<node> arr, int n, int num, int banJing)
{
vector<int> temp(n+1, 0);
int l = 1,zuo;
for (int i = 0; i <= n; i++)
{
zuo = max(l,arr[i].leftIndex);
l = zuo;
for (int j = zuo; j <= n && (arr[j].x - arr[i].x <= banJing); j++)
{
if (num - temp[j] >= arr[i].y)
{
temp[j] += arr[i].y;
arr[i].y = 0;
if (num == temp[j])
l++;
break;
}
else
{
arr[i].y -= (num-temp[j]);
temp[j] = num;
l++;
}
}
if (arr[i].y)
return 0;
}
return 1;
}
//二分查找
int findMinNum(vector<node> &arr,int minNum,int maxNum,int n,int banJing)
{
int le = 1;
sort(arr.begin()+1, arr .end(),cmp);
for (int i = 1; i <= n; i++)
{
while (arr[i].x - arr[le].x > banJing)
le++;
arr[i].leftIndex = le;
arr[i].label = 0;
}
int l = minNum, r = maxNum;
int mid = (l + r) / 2;
while (l <= r)
{
if (testNum3(arr, n, mid, banJing))
{
r = mid - 1;
}
else
{
l = mid + 1;
}
mid = (l + r) / 2;
}
return l;
}
int main()
{
int n, r;
int t;
int minNum=1000000000, maxNum=0;
vector<node> arr;
cin >> t;
while (t--)
{
cin >> n >> r;
arr.resize(n+1);
for (int i = 1; i <= n; i++)
{
cin >> arr[i].x;
cin >> arr[i].y;
minNum = min(minNum, arr[i].y);
maxNum = max(maxNum, arr[i].y);
}
cout << findMinNum(arr, minNum,maxNum, n, r) << endl;
}
system("pause");
return 0;
}