牛客 K-th Number

题意:在给定的数组中找出所有区间的第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 }
View Code

猜你喜欢

转载自www.cnblogs.com/winfor/p/12977002.html