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

题目链接: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;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值