从一个数组A中找出长度不小于K的子段中第K大的数放入数组B中,求B数组中的第M大的数。
先说明一点,在一个序列的子段中找最大数的话,大的概率会比小的概率大。
相对而言,题目在长度不小于K的子段中找第K大,那么小的数成为第K大的数的概率就会比大的数概率大。将数组A的值赋给数组B,对数组B排序,对数组B进行二分,若当前答案作为第K大区间的个数大于M时,那么实际答案呢应该是比这个答案来得大,反之则小。采取尺取法,对左端点进行枚举即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int a[N],b[N];
int n,k;
ll m;
bool check(int x){
int num=0;
ll ans=0;
int l=0,r=-1;
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;
cin>>t;
while(t--){
cin>>n>>k>>m;
for(int i=0;i<n;i++){
cin>>a[i];
b[i]=a[i];
}
sort(b,b+n);
int l=0,r=n-1;
int mid,ans=0;
while(l<=r){
mid=(l+r)/2;
if(check(b[mid])){
ans=b[mid];
l=mid+1;
}
else
r=mid-1;
}
cout<<ans<<endl;
}
return 0;
}
题解参考