做法:二分答案+双指针判定
二分答案比较明显,那么怎么去调整边界呢。
考虑二分出一个答案mid
对数组A进行双指针枚举,左指针固定不动,右指针向右移动
如果当前左右指针之间的区间≥mid的个数≥k个,那么意味着左指针取l,右指针取[r,n]中任意一点所构成的区间的第k大都≥mid
因为在[l,r]这一段≥mid的个数已经≥k个了,在往后的话只有数字对第k大的才有影响,小的都被扔到后面了 而第k大就一定≥mid

每次满足条件后,左指针也右移,这样就计算出所有的子区间第k大≥mid的个数ans
说白了就是利用双指针计算出所有满足区间第k大≥mid的区间个数。
然后ans去跟m作比较,如果ans≥m,说明二分的答案mid偏小,所以二分左边界上调,反之右边界下降。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[1<<17];
ll n,m,k;
bool check(ll x){
    ll l=1,r=0,num=0;
    ll ans=0;
    while(l<=n){
        while(r<n && num<k){
            if(a[++r]>=x) num++;
        }
        if(num==k) ans+=n-r+1;
        if(a[l]>=x) num--;
        ++l;
    }
    return ans>=m;
}
int main(){
    ll _;cin>>_;
    while(_--){
        cin>>n>>k>>m;
        for(int i=1;i<=n;i++) cin>>a[i];
        ll l=0,r=1e9,mid;
        while(l+1<r){
           // cout<<l<<" "<<r<<endl;
            mid=l+r>>1;
            if(check(mid)) l=mid;
            else r=mid;
        }
        cout<<l<<endl;
    }
    return 0;
}