二分典型题

题目大意: 有n个选手每个选手有两种能力值,现在需要第一种能力值的选手X个,第二种能力值的选手Y个。问所有选手中能力值最小的最大是多少。

解题思路: 正向求解完全没有思路,但是我们可以很容易的判断给定一个能力值x,是否存在满足情况的解。于是二分答案。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int MAXN = 500005;
 5 
 6 int n, X, Y;
 7 int s0[MAXN], s1[MAXN];
 8 
 9 int check(int x)
10 {
11     int cnt0 = 0, cnt1 = 0, cnt01 = 0;
12     for (int i = 0; i < n; ++i)
13     {
14         if (s0[i] >= x && s1[i] >= x)
15         {
16             ++cnt01;
17         }
18         if (s0[i] >= x)
19         {
20             ++cnt0;
21         }
22         if (s1[i] >= x)
23         {
24             ++cnt1;
25         }
26     }
27 //    printf("cnt0 = %d cnt1 = %d cnt01= %d\n", cnt0, cnt1, cnt01);
28 //    printf("X = %d  Y  = %d\n", X, Y);
29     if (cnt0>=X && cnt1>=Y && cnt0 + cnt1 - cnt01 >= X+Y)
30     {
31         return 1;
32     }
33     return 0;
34 }
35 
36 void solve()
37 {
38     int l = 1;
39     int r = 10000;
40     while (l <= r)
41     {
42         // printf("l = %d  r = %d\n", l, r);
43         int mid = (l + r)/ 2;
44         // printf("mid = %d check = %d\n", mid, check(mid));
45         if (check(mid))
46         {
47             l = mid + 1;
48         }
49         else
50         {
51             r = mid - 1;
52         }
53     }
54     printf("%d\n", l - 1);
55 }
56 
57 int main()
58 {
59 #ifndef ONLINE_JUDGE
60     freopen("test.txt", "r", stdin);
61 #endif // ONLINE_JUDGE
62     int Case;
63     scanf("%d", &Case);
64     while (Case--)
65     {
66         scanf("%d%d%d", &n, &X, &Y);
67         // printf("X = %d Y = %d\n", X, Y);
68         for (int i = 0; i < n; ++i)
69         {
70             scanf("%d%d", &s0[i], &s1[i]);
71         }
72         solve();
73     }
74     return 0;
75 }

 

posted @ 2018-04-04 09:28  只会一点暴力  阅读(220)  评论(0编辑  收藏  举报