B - K-th Number HDU - 6231 (二分 尺取)

WindowsSource 2017中国大学生程序设计竞赛-哈尔滨站

题意

给一个数组,在所有长度大于等于k的区间内,找出第 \(k\) 大的数,放到另一个数组中,然后在新数组中找到第M大的数。

思路

二分答案,每次二分的时候我们得到一个x
对于每个x 利用尺取,得到 第K大的数大于等于x 的区间一共有多少个

原文1
原文2

代码1

二分下标

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6 + 10;
const int mod = 1e9+7;
int a[N];
int b[N];
int n,k,m;

//求 第K大的数大于等于x   的区间一共有多少个
int check(int x){
    int ans=0;
    int num=0;//j-i之间 大于x的数 的数量
    int j=1;
    for(int i=1;i<=n;i++){
        if(a[i]>=x) num++;
        if(num==k){
            ans+=n-i+1;
            while(a[j]<x){
                ans+=n-i+1;
                j++;
            }
            num--,j++;
        }
    }
    return ans;
}
void solve(){
    cin>>n>>k>>m;
    for(int i=1;i<=n;i++)
        cin>>a[i] , b[i]=a[i];
    sort(b+1,b+n+1);
    int l=1,r=n;
    int ans=0;
    while(l<=r){
        int mid=l+r>>1;
        int x=check(b[mid]);
        if(x==m){
            ans=mid;
            break;
        }
        else if(x>m){
            ans=mid;
            l=mid+1;
        }
        else r=mid-1;
    }
    cout<<b[ans]<<endl;
}
signed main()
{
    int t;
    cin>>t;
    while(t--) solve();
    return 0;
}

代码2

也可以 直接二分数

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int N,K;
ll M;
int a[100005];

bool judge(int x){
    ll ans = 0;
    int num = 0;
    int j = 1;
    for(int i = 1; i <= N; i++){
        if(a[i] >= x)
            num++;
        if(num == K){
            ans += N - i + 1;
            while(a[j] < x){
                ans += N - i + 1;
                j++;
            }
            num--;
            j++;
        }
    }
    if(ans >= M)
        return true;
    else
        return false;
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%lld",&N,&K,&M);
        for(int i = 1; i <= N; i++){
            scanf("%d",&a[i]);
        }
        int l = 1,r = 1000000000;
        int m;
        while(l < r){
            m = l + r >> 1;
            if(judge(m))
                l = m + 1;
            else
                r = m;
        }
        printf("%d\n",l-1);
    }
    return 0;
}
posted @ 2022-11-04 21:58  kingwzun  阅读(36)  评论(0编辑  收藏  举报