把a数组复制到b数组里,给b数组排序
然后用二分法遍历b[i],求所有符合要求的区间的第K值,大于等于b[i]的有多少(用尺取法,详见代码)
如果>=m,那么b[i]应该取更大,否则b[i]应该取更小,就这样二分下去,直到l==r
尺取法时间O(n),二分O(logn),总时间O(nlogn)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<set>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int a[N],b[N];
int n,k;
ll m;
bool judge(int x)
{
ll ans=0;
int l=0,r=-1;
int num=0;
while(r<n)
{
if(num<k)
{
if(a[r+1]>=x) num++;
r++;
}
else
{
if(num==k)ans+=(n-r);
if(a[l]>=x) num--;
l++;
if(ans>=m) return true;
}
}
return false;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%lld",&n,&k,&m);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
memcpy(b,a,sizeof(a));
sort(b,b+n);
int l=0,r=n-1;
int ans;
while(l<=r)
{
int mid=(l+r)>>1;
if(judge(b[mid]))
ans=b[mid],l=mid+1;
else
r=mid-1;
}
printf("%d\n",ans);
}
return 0;
}