zoukankan      html  css  js  c++  java
  • UVA 12174 Shuffle(滑动窗口)

    T*n已经最大已经是10的7次方了,所以这道题虽然暴力枚举前面不完整歌单的情况的思路好想,但是必须用滑动窗口(或者叫尺取法)的技巧来预处理两个数组,这样可以O(n)完成每组数据。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<map>
    #include<set>
    #include<list>
    #include<deque>
    #include<vector>
    #include<algorithm>
    #include<stack>
    #include<queue>
    #include<cctype>
    #include<sstream>
    using namespace std;
    #define pii pair<int,int>
    #define LL long long int
    const double eps=1e-10;
    const int INF=1000000000;
    const int maxn=100000+10;
    int T,n,s,a[maxn],t[maxn],ok[maxn],jie[maxn];
    void qian()//预处理前面的非完整list,jie[i]==1表示
    //最前面那份不完整list能以a[i]结尾
    {
        jie[0]=1;
        memset(t,0,sizeof(int)*(s+1));
    
        for(int i=1; i<s; i++)
        {
            if(i-1>=n||t[a[i-1]]==0)
            {
                if(i-1<n) t[a[i-1]]++;
                jie[i]=1;
            }
            else
            {
                for(int j=i; j<s; j++)
                {
                    jie[j]=0;
                    return;
                }
            }
        }
    }
    void gao()//预处理,ok[i]==1表示以i开始的连续s个数可以组成一个list
    {
        int num=0;
        memset(t,0,sizeof(int)*(s+1));
    
        for(int i=0; i<s; i++)
        {
            if(i>=n)//空位
            {
                num++;
                continue;
            }
            if(t[a[i]]==1)
            {
                ok[0]=0;
                t[a[i]]++;
            }
            else
            {
                num++;
                t[a[i]]++;
            }
        }
        if(num==s) ok[0]=1;
    
        for(int i=1; i<n; i++)
        {
            if(t[a[i-1]]==1) num--;
            t[a[i-1]]--;
    
            if(i+s-1>=n||t[a[i+s-1]]==0) num++;
            if(i+s-1<n) t[a[i+s-1]]++;
    
            if(num==s) ok[i]=1;
            else ok[i]=0;
        }
    }
    int main()
    {
        //freopen("in1.txt","r",stdin);
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&s,&n);
            memset(ok,-1,sizeof(int)*(n+1));
            for(int i=0; i<n; i++)
            {
                scanf("%d",&a[i]);
            }
            int ans=0;
            gao();
            qian();
    
            for(int i=0; i<s; i++)
            {
                if(jie[i])//最前面的逗号点在i之前
                {
                    bool w=1;
                    for(int j=i; j<n; j+=s) //以j开始新的list
                    {
                        if(ok[j]!=1)
                        {
                            w=0;
                            break;
                        }
                    }
                    if(w==1) ans++;
                }
                else
                {
                    break;
                }
            }
    
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    怎样理解HTMLCollection接口
    怎样单独遍历NodeList的键、值和键值对
    怎样获取NodeList某位置上的节点
    怎样遍历NodeList对象
    怎样理解NodeList的动态集合与静态集合
    怎样将类似数组的对象转换为数组
    怎样理解 instanceof
    怎样清理当前节点下的所有文本节点
    怎样移除当前节点
    怎样判断一个节点是否相等 / 是否相同
  • 原文地址:https://www.cnblogs.com/zywscq/p/4309470.html
Copyright © 2011-2022 走看看