hdu 5806 NanoApe Loves Sequence Ⅱ(二分或尺取法)

本文介绍了一种求解区间内第k大的数大于等于给定值m的问题的算法实现,通过枚举左端点结合二分查找或双指针技巧来高效解决问题,并提供了两种不同的代码实现方式。

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

题意:有n个数,求有几个区间中第k大的数大于等于m

思路:考虑枚举左端点,找一个满足的右端点,求最小满足的那个,就是二分求满足的最左端点。

类似于lower_bound,可以看我以前的博客:http://blog.youkuaiyun.com/thehide/article/details/52078438


以下是二分的代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#define maxn 200100
using namespace std;

int presum[maxn];
int main()
{
    int t,a;
    scanf("%d",&t);
    while(t--){
        memset(presum,0,sizeof presum);
        int n,m,k;
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;i++){
            scanf("%d",&a);
            presum[i] = presum[i-1];
            if(a >= m) presum[i]++;
        }
        long long ans = 0;
        for(int i = 1;i+k-1 <=n;i++){
            int low = i+k-1,high = n;
            int mark = -1;
            while(low <= high){
                int mid = (low+high) >>1;
                int cnt = presum[mid] - presum[i-1];
                if(cnt >= k){
                    mark = mid;
                    high = mid-1;
                }
                else{
                    low = mid + 1;
                }
            }
            if(mark!=-1) ans += n - mark + 1;


        }
        printf("%I64d\n",ans);
    }

    return 0;
}


官方题解:双指针?还是尺取法..

将不小于mm的数看作11,剩下的数看作00,那么只要区间内11的个数不小于kk则可行,枚举左端点,右端点可以通过two-pointer求出。

时间复杂度O(n)O(n)

附上自己写的代码..感觉快超时了。

#include <stdio.h>
#define maxn 200100

int a[maxn];

int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        int n,m,k;
        scanf("%d%d%d",&n,&m,&k);
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);a[i] = a[i]>=m?1:0;
        }
        int low = 0,high = 0,cnt = 0;
        long long ans = 0;
        while(high < n){
            while(high < n && (cnt = cnt + a[high++]) < k);
            while(cnt == k){
                ans+=(long long)n-high+1;
                cnt -= a[low++];
            }
        }
        printf("%I64d\n",ans);
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值