HDU - 5806 :NanoApe Loves Sequence Ⅱ(尺取)

原题链接
NanoApe, the Retired Dog, has returned back to prepare for for the National Higher Education Entrance Examination!

In math class, NanoApe picked up sequences once again. He wrote down a sequence with n numbers and a number m on the paper.

Now he wants to know the number of continous subsequences of the sequence in such a manner that the k-th largest number in the subsequence is no less than m.

Note : The length of the subsequence must be no less than k.
Input
The first line of the input contains an integer T, denoting the number of test cases.

In each test case, the first line of the input contains three integers n,m,k.

The second line of the input contains n integers A1,A2,…,An, denoting the elements of the sequence.

1≤T≤10, 2≤n≤200000, 1≤k≤n/2, 1≤m,Ai≤109
Output
For each test case, print a line with one integer, denoting the answer.
Sample Input
1
7 4 2
4 2 7 7 6 5 1
Sample Output
18

题目描述

有n个数字的序列,要求你找出子序列长度不小于k且这个子序列中第k大的数字不小于m的数量
思路:(尺取)取出一个区间内存在 num 个数字 >= m,并且这num == k,那么无论你在往这个区间加入一个 >= m的数还是一个 < m的数都是一个满足要求的子序列,所以我们只需要计算出后面的数字个数,就可以得到这么多个子序列,然后重复上述操作
例如:样例中k = 2、m = 4,那么我们先取到2(k)个 >= m的数字,即 4 2 7,那么后面的序列无论你怎么加数字他们都可以符合要求
代码如下

#include <stdio.h>
#include <iostream>
#include <algorithm>

using namespace std;

int a[200000];

int main()
{
    int i,j,t,n,k,m,num;//num用来记录尺取区间大于等于m的数字个数
    long long ans;//记录满足子序列的个数
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d %d",&n,&m,&k);
        for(i = 0;i < n;i++)
            scanf("%d",&a[i]);
        i = j = ans = num = 0;
        while(1)
        {
            while(j < n && num < k)
            {
                if(a[j++] >= m)
                    num++;
            }
            //该区间不符合条件,那么后面也就不可能了,结束循环
            if(num < k)
            	break;
            //找到了恰好满足条件的序列,那么后面的序列都满足,所以加上 n-j ,记得加1(本身序列)
            if(num >= k)
                ans += (n - j + 1);
           	//如果该区间的第一个元素大于等于m,那么num--
            if(a[i] >= m)
                num--;
            i++;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值