codeforces 190D Non-Secret Cypher(two pointers)

题目链接

Non-Secret Cypher
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Berland starts to seize the initiative on the war with Flatland. To drive the enemy from their native land, the berlanders need to know exactly how many more flatland soldiers are left in the enemy's reserve. Fortunately, the scouts captured an enemy in the morning, who had a secret encrypted message with the information the berlanders needed so much.

The captured enemy had an array of positive integers. Berland intelligence have long been aware of the flatland code: to convey the message, which contained a number m, the enemies use an array of integers a. The number of its subarrays, in which there are at leastk equal numbers, equals m. The number k has long been known in the Berland army so General Touristov has once again asked Corporal Vasya to perform a simple task: to decipher the flatlanders' message.

Help Vasya, given an array of integers a and number k, find the number of subarrays of the array of numbers a, which has at least kequal numbers.

Subarray a[i... j] (1 ≤ i ≤ j ≤ n) of array a = (a1, a2, ..., an) is an array, made from its consecutive elements, starting from the i-th one and ending with the j-th one: a[i... j] = (ai, ai + 1, ..., aj).

Input

The first line contains two space-separated integers nk (1 ≤ k ≤ n ≤ 4·105), showing how many numbers an array has and how many equal numbers the subarrays are required to have, correspondingly.

The second line contains n space-separated integers ai (1 ≤ ai ≤ 109) — elements of the array.

Output

Print the single number — the number of such subarrays of array a, that they have at least k equal integers.

Please do not use the %lld specifier to read or write 64-bit integers in С++. In is preferred to use the cincout streams or the %I64dspecifier.

Sample test(s)
input
4 2
1 2 1 2
output
3
input
5 3
1 2 1 1 3
output
2
input
3 1
1 1 1
output
6
题意:已知一个数列a(a1,a2.......an)。求这个数列有多少个子数列满足条件?

子数列为数列a中下标从L到R连续的一段数字,其中1<=L<=R<=n。

若一个子数列中相同的数字个数大于等于K个,则满足条件。

题解:我们可以用two pointer的方法。维护两个指针,左指针L,右指针R。表示当前的区间为[L,R]。如果当前区间满足条件,则L后移一位,否则R后移一位。我们可以用map或者hash统计区间中每个数字的个数。初始的时候L=R=1。在维护的过程中我们可以O(1)判断出一个区间是否满足条件。

如何统计答案的个数?

当我们求得一个满足条件的区间[L,R]以后,所有包含这个区间的区间都满足条件。但是对于每个区间答案直接加上L*(n-R+1)是不对的,为了避免算重的情况。我们在two pointer的时候记录当前区间的前一个满足条件的区间 [preL,preR]。答案加上(L-preL)*(n-R+1)就对了。

代码如下:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define inff 0x3fffffff
#define nn 410000
#define mod 1000000007
typedef long long LL;
const LL inf64=inff*(LL)inff;
using namespace std;
int n,k;
int a[nn];
mapma;
int main()
{
    int i;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        for(i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        ma.clear();
        int pl;
        pl=0;
        int l,r;
        l=1,r=0;
        bool ok=false;
        LL ans=0;
        while(r<=n)
        {
            if(ok)
            {
                ans+=LL(n-r+1)*(LL)(l-pl);
                pl=l;
                if(ma[a[l]]==k)
                    ok=false;
                ma[a[l]]--;
                l++;
            }
            else
            {
                r++;
                if(r<=n)
                {
                    if(ma.count(a[r])==0)
                        ma[a[r]]=1;
                    else
                        ma[a[r]]++;
                    if(ma[a[r]]==k)
                    {
                        ok=true;
                    }
                    else
                        ok=false;
                }
            }
        }
        printf("%I64d\n",ans);
    }
    return 0;
}


你可能感兴趣的:(two,pointers)