2017CCPC 哈尔滨 B

 

这题没有考虑到m这个东西,所以就没有往二分答案的方向想

 

二分答案

 

check的时候,我们找的是大于等于x的数有多少个被加入到那个数组中。如果 >= m说明这个数可能是答案,否则就不是。

 

用尺取来计数,还算比较好理解。

 

 

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 int n,k;
 6 long long m;
 7 
 8 int a[100005];
 9 int b[100005];
10 
11 bool check(int x) {
12 
13     long long ans = 0;
14     int num = 0;
15     int pos = 1;
16 
17     for(int i = 1; i <= n; i++) {
18         if(a[i] >= x) {
19             num++;
20         }
21         if(num == k) {
22 
23             // 后面形成的区间,x作为第k大,或者有比它大的
24             // 但是一定会有n - i + 1个大于等于x的数被加入到ans数组中
25             ans += n - i + 1;
26 
27             // 如果左端这个数小于x
28             // 那么去掉他没有影响
29             // 依然会有n - i + 1个大于等于x的数加入到ans数组中
30             while(a[pos] < x) {
31                 ans += n - i + 1;
32                 pos++;
33             }
34             pos++;
35             num--;
36         }
37 
38 
39     }
40 
41     //cout<<ans<<endl;
42     if(ans >= m) return true;
43     return false;
44 }
45 
46 int main() {
47 
48     int t;
49     scanf("%d",&t);
50 
51     while(t--) {
52         scanf("%d %d %lld",&n,&k,&m);
53 
54         for(int i = 1; i <= n; i++) {
55             scanf("%d",&a[i]);
56         }
57 
58         //cout<<num<<endl;
59         int L = 1,R = 1000000001;
60         int mid;
61         while(R - L > 1) {
62             mid = L + R >> 1;
63 
64             //cout<<mid<<' '<<b[mid]<<endl;
65             if(check(mid)) {
66                 L = mid;
67             }
68             else {
69                 R = mid;
70             }
71         }
72 
73 
74         printf("%d\n",L);
75 
76     }
77 
78 
79 
80 
81 
82     return 0;
83 }

 

posted @ 2018-10-01 21:55  汪汪鱼  阅读(290)  评论(0编辑  收藏  举报