hdu6231 K-th Number(二分答案+尺取)

本文解析了HDU 6231题目的解题思路,通过二分查找及区间统计的方法,求解特定条件下第m大的数。介绍了如何利用排序和二分搜索技巧解决此类问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=6231

题意:

输入n,k,m,需要求在n个数的a数组中,任意区间里选择第k大的数存入b数组,在b数组中求得第m大的数

解:

其实一开始没懂怎么去解这道题,但可以反过来想想,如果我是b数组中一个数如何满足题目所要求的条件 ?

首先将a数组存入b数组,且将b数组排序,二分下标得到b[mid],判断b[mid]在a数组中的任意区间里有多少种情况存在那么一个第k大的数,

如果存在的情况大于m,那么该数偏小;若小于m,则该数偏大;

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>

using namespace std;
//先在b数组(b数组为a数组中的各项元素且排好序)中二分一个数x
//将x放置在a中进行比较查找,找到第k大的数记录位置后,用n减去该下标
//因为区间任意,所以k的可能性就有n-r的累加
//最后结果如果比m大,那么该x偏小;如果比m小,那么该x偏大
//结果与m比较的意义在于,k的存在数目比m大的话表明有足够的k拼凑出m;
const int maxn = 1e5+20;
typedef long long ll;
ll a[maxn],b[maxn];
ll k,m,n;
ll judge(ll x)
{
    ll num=0;
    ll l=1,r=0;
    ll sum=0;
    while(r<=n)
    {
        if(num<k)
        {
           if(a[r+1]>=x)num++;
           r++;
        }
        else
        {
            if(num==k)sum+=n-r+1;
            if(a[l]>=x)num--;
            l++;
        }
    }
    return sum;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%I64d%I64d%I64d",&n,&k,&m);
        for(int i=1;i<=n;i++)
        {scanf("%I64d",&a[i]);b[i]=a[i];}
        sort(b+1,b+1+n);
        int l=1,r=n;ll ans=0;
        int mid;
        //cout<<"1"<<endl;
        while(r>=l)
        {
            mid=(r+l)/2;
            //cout<<"3"<<endl;
            if(judge(b[mid])>=m)
            {
                ans=b[mid];
                l=mid+1;
            }
            else
            r=mid-1;
        }
        //cout<<"2"<<endl;
        printf("%I64d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值