HDU5806 NanoApe Loves Sequence Ⅱ(尺取法\two pointers)

HDU5806 NanoApe Loves Sequence Ⅱ(尺取法\two pointers)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5806


题目

Time Limit:2000MS Memory Limit:131072KB
Description
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.

1T10, 2n200000, 1kn/2, 1m,Ai109

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,m,k,并给你一个长度为n的数列。让你求他们的最大连续子序列个数,要求连续子序列要满足数列中第k大的数大于等于m。


分析

题目数据范围较大,使用暴力枚举一定会TLE。
使用尺取法(two pointers)来做即可,核心思想是记录前缀和。 其次,对于 a1a2a3a4an ,每次完成当前枚举的区间之后,只需要++右端点的值,左端点不需要重置回去。(因为比如当前区间左端点为 a4 那么 [a4,ai] 满足条件时一定可以保证 [a1,ai] 也满足。详细见代码

后注:如果数据不是很强,可以用树状数组水过。但是写了一发树状数组T了,看来数据的确非常强。


源码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
#include<string>
#include<sstream>
#include<cmath>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<utility>
#include<sstream>
#define mem0(x) memset(x,0,sizeof x)
#define mem1(x) memset(x,-1,sizeof x)
#define dbug cout<<"here"<<endl;
//#define LOCAL

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int MAXN = 200010;
const int MOD = 1000000007;

int s[MAXN];

int main(){
    //two pointers 尺取法
    #ifdef LOCAL
        freopen("C:\\Users\\asus-z\\Desktop\\input.txt","r",stdin);
        freopen("C:\\Users\\asus-z\\Desktop\\output.txt","w",stdout);
    #endif
    int t;
    ll tmp;
    scanf("%d", &t);
    while(t--){
        ll n,m,k;
        mem0(s);
        scanf("%I64d%I64d%I64d", &n, &m, &k);
        for(int i = 1; i <= n; ++i){
            scanf("%I64d", &tmp);
            s[i] = s[i-1];
            if(tmp >= m)
                s[i]++;
        }
        ll l, r, cnt;
        l = 0;
        r = k;
        cnt = 0;
        while(r <= n){
            while(s[r]-s[l] >= k)
                l++;
            cnt += l;
            r++;
        }
        printf("%I64d\n", cnt);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值