• luogu题解 UVA11536 【Smallest Sub-Array】最短set区间&滑动窗口


    • 题目链接:

      https://www.luogu.org/problemnew/show/UVA11536

    • 题目大意:

      给定一个(N,M,K),构造这样的数列:

      (x[1]=1,x[2]=2,x[3]=3)
      (x[i]=(x[i-1]+x[i-2]+x[i-3])mod M+1(N>=i>=4))

      然后问你是否存在一个在(x[1])(x[n])中的区间,使得([1,K])所有元素在其中至少出现过一次。

      若存在,输出这个区间最短长度;否则输出("sequence) (nai")

      有T组数据

    • 分析:

      我们可以想到用滑动窗口的改进做法。

      搞一个左指针(l),右指针(r),和一个(cnt)数组记录每个元素相对应在([l,r])中的出现次数。

      然后不断尝试右移(r),同时将(cnt[x[r]]++),如果(cnt[x[r]]==1),就让(done++),表示多了一个新元素出现在区间内,如果(done==k),说明所有元素出现过一次,这时尝试右移左指针,用上面类似的操作,只不过判定有所区别,直到(done!=k)说明不满足性质,记录下此时(r-l)长度,再重复右移(r)的操作

      其实如果你对莫队有了解的话这些应该很容易理解

    • 注意:

      庆幸的是由于(mod M)的限制,数列中的数都很小,可以直接记录,不必用map或离散化

    • 代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cctype>
    #define inf 0xfffffff
    using namespace std;
    const int maxn=1000009;
    int t,n,m,k;
    int f[maxn];
    int cnt[1005];
    int main(){
        scanf("%d",&t);
        for(register int ite=1;ite<=t;ite++){
        	memset(cnt,0,sizeof(cnt));
            scanf("%d %d %d",&n,&m,&k);
            f[1]=1,f[2]=2,f[3]=3;
            for(register int i=4;i<=n;i++)f[i]=(f[i-1]+f[i-2]+f[i-3])%m+1;
            int l=1,r=1,done=0,ans=inf;
            while(r<n){
                int g=f[r++];
                if(g>=1&&g<=k)cnt[g]++;
                if(cnt[g]==1)done++;
                while(done==k&&l<r){
                    ans=min(ans,r-l);
                    g=f[l++];
                    cnt[g]--;
                    if(cnt[g]==0)done--;
                }
            }
            printf("Case %d: ",ite);
            if(ans==inf)puts("sequence nai");
            else printf("%d
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    json.net的常用语句JsonConvert.SerializeObject(对象)
    struts2国际化
    多浏览器兼容性问题及解决方案之Javascript篇
    对XMLHttpRequest异步请求的面向对象封装
    java的学习资料
    多浏览器兼容性问题及解决方案之CSS篇
    jQuery库与其他JS库冲突的解决办法
    abstract virtual interface区别
    项目优化经验——垃圾回收导致的性能问题(转)
    C#实现小写金额转大写金额
  • 原文地址:https://www.cnblogs.com/Rye-Catcher/p/9094648.html
Copyright © 2020-2023  润新知