题目链接:http://codeforces.com/problemset/problem/702/C
题意:
在数轴上有N个城市和M个信号塔,给你这N个城市以及M个塔在数轴上的位置,求M个塔可以覆盖N个城市的最小半径r。
思路:
刚开始想的是,对半径进行二分,但是考虑到每次对半径进行二分后,要判断这M个塔是否已经可以覆盖N个城市,判断这里找不到时间复杂度比较好的写法。后面想了想,对于每个城市,找到距离其最近的塔,计算出距离,在这N个距离中取最大的距离,就是最后要找的最小半径r了,这里同样利用二分来找距离城市最进的塔,二分的时候找到距离城市右边最近的塔,然后和城市左边第一个塔和城市的距离做判断,取较小的,就是距离城市最近的塔到城市的距离了。
代码:
1 #include <iostream> 2 #include <cmath> 3 #include <cstdio> 4 #include <cstring> 5 #include <cstdlib> 6 #include <stack> 7 #include <queue> 8 #include <vector> 9 #include <algorithm> 10 #include <string> 11 #define mearv(a, b) memset(a, b, sizeof(a)) 12 #define mestrc(a, b, c) memset(&(a), b, sizeof(c)) 13 14 typedef long long LL; 15 using namespace std; 16 const int MAXN = 100000; 17 const LL INF = 1e15; 18 19 int main() { 20 LL a[MAXN + 3] = {0}, b[MAXN + 3] = {0}; 21 LL n, m; 22 scanf("%I64d%I64d", &n, &m); 23 for(int i = 0; i < n; i++) scanf("%I64d", &a[i]); 24 for(int i = 0; i < m; i++) scanf("%I64d", &b[i]); 25 b[m] = INF; 26 LL ans = -1; 27 for(int i = 0; i < n; i++){ 28 int lo = 0, hi = m; 29 while(lo <= hi){//对塔进行二分,找到城市右边距离城市最进的塔。 30 int mid = (lo + hi) >> 1; 31 if(a[i] <= b[mid]) hi = mid - 1; 32 else lo = mid + 1; 33 } 34 int minn = lo; 35 if(lo > 0 && (b[lo] - a[i] > a[i] - b[lo - 1]) ) minn = lo - 1;//和城市左边第一个塔进行比较 36 ans = max(ans, abs(b[minn] - a[i]));//每次结果取最大值 37 } 38 printf("%I64d ", ans); 39 return 0; 40 }