11536 Smallest Sub-Array(入门级TwoPoint)

先按照题目的意思把序列求出来。

最后就是用TwoPoint的思想了。

r表示入,l表示出。

每进入一了就mp[a[r]]++, 如果a[r] <= k && mp[a[r]] == 1的话,就说明r-l之间又多了一种合法数了,cnt++;

当cat == k时,这个时候就要把里面的数往外拿了,直到序列为空或者是cnt < k时break;

int nCase = 0;
const int maxn = 1000005;
int mp[maxn];//Count[a, b]
int a[maxn];
int n, m, k;
void init()
{
    a[1] = 1, a[2] = 2, a[3] = 3;
    for (int i = 4;i <= n + 1;++i)
        a[i] = (a[i - 1] + a[i - 2] + a[i - 3]) % m + 1;
}
int main()
{
    //freopen("in.txt","r",stdin);
    //frepoen("out.txt","w",stdout);
    int t;
    cin >> t;
    while(t--)
    {
        cin >> n >> m >> k;
        memset(mp, 0,sizeof mp);
        init();
        int l = 1;
        int len = inf;
        int cnt = 0;
        for (int r = 1;r <= n;++r)
        {
            mp[a[r]]++;
            if (mp[a[r]] == 1 && a[r] <= k && a[r] >= 1) cnt++;
            while (cnt == k && l <= r)
            {
                len = min(len, r - l + 1);
                mp[a[l++]]--;
                if (mp[a[l-1]] == 0 && a[l-1] <= k) cnt--;
                //len = min(len, r - l + 1);
            }
        }
        cout << "Case " << ++nCase << ": ";
        //printf("Case %d: ", ++nCase);
        if (len > n) cout << "sequence nai" << endl;
        else cout << len << endl;
    }
    return 0;
}


你可能感兴趣的:(11536 Smallest Sub-Array(入门级TwoPoint))