首先可知答案的数字具有一定的单调性。考虑使用二分答案的方式。
如何验证:已知这个数字,去区间里面找有多少个数比当前这个数字大,如果数量大于等于m的话证明该数小了,需要向右移动反之向左移动。
在统计区间里面有多少个数比当前的数字大的时候,要注意使用双指针的方式,否则会超时。还有就是要用long long。
//双指针加二分做法。 #include <bits/stdc++.h> typedef long long ll; using namespace std; const int maxn = 1e5+10; ll N, K, M; ll a[maxn]; bool yanz(ll x) { ll num=0,s=0; for(int i=1,j=1;j<=N;j++) { if(a[j]>=x) num++;///值大于X if(num==K)///出现k个值大于等于X { s+=N-j+1;///将右边界大于等于j的区间都算上 while(a[i]<x) s+=N-j+1,i++;///左边界右移 如果num没少 又加一次右边界等于大于j的区间 num--;i++;///这个左边界值大于X } } return s>=M; } int main() { int T, max; scanf("%d", &T); while (T--) { scanf("%lld %lld %lld", &N, &K, &M); for (int i=1;i<=N;i++) { scanf("%lld", a+i); max = max>a[i]? max:a[i]; } //二分答案 ll l = 1, r = 1e9, ans=0; while (l<r) { ll mid = (l+r+1)/2; if (yanz(mid)) { ans = mid; l = mid; } else r = mid-1; } printf("%lld\n", ans); // cout<<yanz(8)<<endl; } return 0; }