hdu 5806 NanoApe Loves Sequence Ⅱ

題目鏈接:hdu 5806

NanoApe Loves Sequence Ⅱ

Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/131072 K (Java/Others)

Problem 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.

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

比賽的時候真是太不冷靜了……第二天早上一下就想出來了。實現水平不行,調試還是費了點時間。int又炸。

看題面直接暴力妥妥的TLE,所以考慮降低複雜度。
設一個p記錄此時子串的第一個元素的下標,i則爲此子串的最後一個元素的下標。模擬出隊入隊。

設一個cnt記錄當前選中的子串中比m大的數的個數,一開始先使新元素入隊,直到cnt == k時ans就加上n - i(正好爲以現在選中的子串爲前綴的子串的數量),然後考慮p1後移,以選中新的子串,如果arr[p1] < m,那麼它出隊不會使第k大的數發生變化,我們使p1++,此時形成了一個新的子串,因此ans要再次加n - i,如此重複直到arr[p1] >= m爲止。

如果一開始arr[p1] >= m,就直接使p1++,cnt- -,第一個元素出隊。

當元素出隊到cnt < k時,再使後面的元素依次入隊。

#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define MAX 200005
#define mod 1000000007
#define INF -0x3f3f3f3f

using namespace std;

int arr[MAX];

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        long long int n, m, i = 0ll;
        int k;
        scanf("%I64d %I64d %d", &n, &m, &k);
        for(; i < n; i++)
        {
            scanf("%d", &arr[i]);
        }

        int cnt = 0, p1 = 0;
        long long int ans = 0;
        for(i = 0ll; i < n; i++)
        {
            if(cnt == k)
                break;
            else if(arr[i] >= m)
                cnt++;
        }
        i--;
        while(i < n)
        {
            //printf("i:%d\n", i);
            if(cnt == k)
            {
                ans += n - i;
                //printf("ans1:%d\n", ans);
                while(arr[p1] < m)//滿足此條件時第一個元素出隊不會影響第k大的值。
                {
                    p1++;
                    ans += n - i;
                    //printf("ans2:%d\n", ans);
                }
                p1++;
                cnt--;
                //printf("%d\n", p1);
            }
            else
            {
                i++;//cnt < k時,i後移使新元素入隊。
                if(arr[i] >= m)
                    cnt++;
            }
        }
        printf("%I64d\n", ans);
    }
    return 0;
}

運行結果:
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章