UVa 11536:Smallest Sub-Array(滑动窗口)

来源:互联网 发布:js的随机数生成 编辑:程序博客网 时间:2024/05/17 02:35

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=845&page=show_problem&problem=2531

有n(n106)个0 ~ m - 1(m1000)的整数组成一个序列。输入k(k100),你的任务是找一个尽量短的连续的子序列(xa,xa+1,xa+2,...,xb1,xb),使得该子序列包含1 ~ k的所有整数。例如,n = 20, m = 12, k = 4,序列为1 ( 2 3 7 1 12 9 6 3 7 5 4 ) 5 3 1 10 3 3,括号内部分是最优解。如果不存在满足条件的连续子序列,输出sequence nai。(本段摘自《算法竞赛入门经典(第2版)》)

分析:
        滑动窗口思想,直接扫描一遍即可,复杂度为O(n)

代码:

#include <iostream>#include <fstream>#include <cstring>#include <vector>#include <queue>#include <cmath>#include <stack>using namespace std;const int maxn = 1000000 + 5, INF = 1000000 + 5;int T, n, m, k, num, ans, tmp;int a[maxn], x[105];int main(){    scanf("%d", &T);    for (int C = 0; C < T; ++C)    {        scanf("%d%d%d", &n, &m, &k);        a[0] = 1;        a[1] = 2;        a[2] = 3;        for (int i = 3; i < n; ++i)            a[i] = ((a[i - 3] + a[i - 2] + a[i - 1]) % m) + 1;        ans = INF;        num = 0;        memset(x, 0, sizeof(x));        queue< int > q;        for (int i = 0; i < n; ++i)        {            if (a[i] <= k)            {                q.push(i);                ++x[a[i]];                if (x[a[i]] == 1)                    ++num;            }            while (num == k)            {                tmp = i - q.front() + 1;                ans = min(ans, tmp);                if (--x[a[q.front()]] == 0)                    --num;                q.pop();            }        }        printf("Case %d: ", C + 1);        if (ans != INF)            printf("%d\n", ans);        else            printf("sequence nai\n");    }    return 0;}
0 0
原创粉丝点击