题意:在给定的数组中找出所有区间的第k大的数 全部放入另一个数组中 然后求另一个数组中的第M大
题目链接:https://ac.nowcoder.com/acm/problem/14301
思路:用二分check mid来做
如何判断cehck的条件呢
假设当前的数为 mid
那么在一个区间中如果找到k个大于等于mid的数 那么这个区间的第k个数>=mid
并且如果有m个这样的区间 就证明另一个数组中的第M大>=mid
这样就可以满足check的条件, 而求区间用尺取法o(n)求 总复杂度o(nlogn)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define pb push_back 5 const int maxn =1e5+10; 6 ll m;// 可能会有很多数 7 int n,k; 8 int a[maxn]; 9 int check(int x) 10 { 11 ll cnt=0; 12 int l=1,r=1; 13 int sum=0; 14 while(r<=n) 15 { 16 if(a[r]>=x) 17 { 18 sum++; 19 } 20 if(sum==k) 21 { 22 cnt+=n-r+1; 23 while(a[l]<x)//当前这个数没用 那么可以记下一个数 24 { 25 cnt+=n-r+1; 26 l++; 27 } 28 l++;//这个数已经被使用过 所以移到下一位 29 sum--; 30 } 31 r++; 32 } 33 if(cnt>=m) 34 return 1; 35 return 0; 36 } 37 int main() 38 { 39 ios::sync_with_stdio(false); 40 cin.tie(0); 41 int t; 42 cin>>t; 43 while(t--) 44 { 45 cin>>n>>k>>m; 46 for(int i=1;i<=n;i++) 47 { 48 cin>>a[i]; 49 } 50 int l=1,r=1e9; 51 int ans=0; 52 while(l<=r) 53 { 54 int mid=(l+r)/2; 55 if(check(mid)) 56 { 57 l=mid+1; 58 ans=mid; 59 } 60 else 61 r=mid-1; 62 } 63 cout<<ans<<'\n'; 64 } 65 66 }