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;
}
發佈了56 篇原創文章 · 獲贊 16 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章