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 }