题目链接
题目思路
二分+尺取法
题目大意是从a中找长度大于k的区间中第k大的数放入b中,然后在b中找到第m大的数,即为answer
然后可以这样想,假设第m大的数为x,那么应该有m个区间,其中有k个大于等于x的。当取x,有k大于等于x区间数量>=m时,x肯定是取小了,反之则取大了
区间用尺取法,找x用二分法
一直疑问为什么l=mid+1,ans=mid,因为mid刚好为答案ans时,区间数量是等于m的。(多练习二分)
代码实现
#include<bits/stdc++.h> using namespace std; #define ll long long const int Max=1e5+5; ll x,n,k,m,a[Max]; bool check(int x) { ll l=1,r=0,ans=0,num=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++; } if(ans>=m) return 1; else return 0; } int main() { int t; cin>>t; while(t--) { ll mina=0,maxa=1e9; cin>>n>>k>>m; for(int i=1;i<=n;i++) { cin>>a[i]; mina=min(mina,a[i]); maxa=max(maxa,a[i]); } ll la=mina,ra=maxa,ansa=-1; while(la<=ra) { ll mid=(la+ra)/2; if(check(mid)) la=mid+1,ansa=mid; else ra=mid-1; } cout<<ansa<<endl; } }