洛谷P1316 丢瓶盖【二分】【贪心】

题目https://www.luogu.org/problemnew/show/P1316

题意:

给定a个点的坐标(在一条直线上),现在要选b个点,问这b个点的最近距离的最大值是多少。

思路:

感觉数据量大的题目要大胆去考虑二分答案。

题目没有说给定的坐标有序,所以要先排个序。

然后二分答案,贪心的验证这个距离是不是可行的。

统计距离超过当前值的点有多少个,如果少于b说明取不到当前的答案。

这里不需要去考虑他们的最小值是不是刚好是当前值,因为最小值一定是大于等于当前答案的,如果不等于的化,那一定会在之后的二分过程中被更新。

贪心的原因是我们实际上是在选尽可能多的点满足他们之间的距离都大于当前答案。

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<map>
 4 #include<set>
 5 #include<iostream>
 6 #include<cstring>
 7 #include<algorithm>
 8 #include<vector>
 9 #include<cmath> 
10 #include<queue>
11 
12 #define inf 0x7fffffff
13 using namespace std;
14 typedef long long LL;
15 typedef pair<int, int> pr;
16 
17 int a, b;
18 const int maxn = 1e5 + 5;
19 LL pos[maxn];
20 
21 bool check(LL x)
22 {
23     //int dis = inf;
24     int pre = 1, cnt = 1;
25     for(int i = 2; i <= a; i++){
26         if(pos[i] - pos[pre] >= x){
27             //dis = min(dis, pos[i] - pos[pre]);
28             pre = i;
29             cnt++;
30         }
31         //if(cnt == b)break;
32     }
33     if(cnt < b){
34         return false;
35     }
36     else return true;
37 }
38  
39 int main()
40 {
41     scanf("%d%d", &a, &b);
42     for(int i = 1; i <= a; i++){
43         scanf("%lld", &pos[i]);
44     }
45     sort(pos + 1, pos + 1 + a);
46     //for(int i = 1; i <= a; i++)cout<<pos[i]<<" ";
47     //cout<<endl;
48     
49     LL st = 0, ed = pos[a] - pos[1], ans;
50     while(st <= ed){
51         LL mid = (st + ed) / 2;
52         if(check(mid)){
53             ans = mid;
54             //ans = max(ans, mid);
55             st = mid + 1;
56         }
57         else{
58             ed = mid - 1;
59         }
60     }
61     printf("%lld\n", ans);
62     return 0;
63 }

 

posted @ 2019-02-15 20:19  wyboooo  阅读(270)  评论(0编辑  收藏  举报