zoukankan      html  css  js  c++  java
  • Codeforces Round #215 (Div. 2) D. Sereja ans Anagrams

    http://codeforces.com/contest/368/problem/D

    题意:有a、b两个数组,a数组有n个数,b数组有m个数,现在给出一个p,要你找出所有的位置q,使得位置q  q+p   q+2*p  .....q+(m-1)*p   经过一定的操作(不改变数据大小)全等于b数组。

    思路:首先肯定对a数组离散,然后二分对a、b数组分配好离散后的值。其实我们只需要枚举0————p位置,哈希记录,然后从q----一直滚到q(m-1)*p>=n,对于一个数据,出来第一个数,进去最后一个数。

    这样,如果没有避免对b数组扫描一次,那么还是会超时,额,我在这里超时了几次。这个题目的核心就是如何避免再一次扫描b数组,因为我要判断挑出来的m个值与b数组全等........其实可以这样,我们把b数组里的数据都记录一次,比如b[10]={1,2,3,1,2,3,4,5,1,2};

    那么我们对于b数组哈希的话,就是vist[1]=3    vist[2]=3    vist[3]=2    vist[4]=1    vist[5]=1   那么,如果说要有一个数来记录b有几种不想等的数据的话,那么k=5;

    那么同样的,我们会对于从a数组里面挑出来的m个值进行哈希,那么有vist1[1]   vist1[2]   vist1[3]   vist1[4]   vist1[5];

    当且仅当,vist[1]==vist1[1]   vist[2]==vist1[2]   vist[3]==vist1[3]   vist[4]==vist1[4]   vist[5]==vist1[5]时,与b全等,那么也就是说

    在严格挑选出来的m各值,要有m种数,并且,这m种数要等于k,如此就可以说挑出来的m个数就是b数组.........

    那么其实,只要有vist[i]>0时  有vist[i]==vist1[i]    那就m++    如果某个操作,弹出来一个值,使得原本vist[i]>0时  有vist[i]==vist1[i]的,现在不想等了,那么就m--;

    ac代码:

    额,还需要注意一点,这个数据有的地方会超int型,所以,用__int64比较好把
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int vist[200005],vist1[200005];
    int a[200005],b[200005],s[200005];
    int total[200005],vist2[200005];
    int vist3[200005];
    int erfen(int ll,int rr,int ans)
    {
        while(ll<=rr)
        {
            int mid=(ll+rr)/2;
            if(s[mid]>ans)
                rr=mid-1;
            else  ll=mid+1;
        }
        return rr;
    }
    int main()
    {
        int n,m,p;
        while(scanf("%d%d%d",&n,&m,&p)>0)
        {
            for(int i=0; i<n; i++)
            {
                scanf("%d",&a[i]);
                s[i]=a[i];
            }
            sort(s,s+n);
            int cnt=1;
            for(int i=1; i<n; i++)
                if(s[i]!=s[i-1])
                    s[cnt++]=s[i];
            sort(s,s+cnt);
            memset(vist,0,sizeof(vist));
            memset(vist1,0,sizeof(vist1));
            memset(vist2,0,sizeof(vist2));
            memset(vist3,0,sizeof(vist3));
            //for(int i=0;i<n;i++)
            //vist[s[i]]=i+1;
            for(int i=0; i<m; i++)
                scanf("%d",&b[i]);
    
            for(int i=0; i<n; i++)
            {
                int id=erfen(0,cnt-1,a[i]);
                vist[id]=1;
                a[i]=id;
            }
            int flg=1;
            int ans=0,ans1=0;
            for(int i=0; i<m; i++)
            {
                int id=erfen(0,cnt-1,b[i]);
                if(b[i]==s[id])
                {
                    if(vist1[id]==0)
                        ans++;
                    vist1[id]++;
                }
    
                else
                {
                    flg=0;
                    break;
                }
                b[i]=id;
    
                //vist2[id]=1;
            }
    
            if(flg==0)
            {
                printf("0
    ");
                continue;
            }
            int sum=0;
            for(int i=0; i<p; i++)
            {
    
                if((__int64)i+(__int64)(m-1)*(__int64)p>=n)
                    break;
    
                for(int j=0; j<m; j++)
                {
                    if((__int64)i+(__int64)j*(__int64)p>=n)
                        break;
                    int y=a[i+j*p];
                    if(vist1[y])
                    {
                        vist2[y]++;
                        if(vist2[y]==vist1[y])
                        {
                            ans1++;
                            vist3[y]=0;
                        }
                        if(vist2[y]>vist1[y]&&vist3[y]==0)
                        {
                            ans1--;
                            vist3[y]=1;
                        }
                    }
    
                }
                if(ans1==ans)
                {
                    total[sum++]=i;
                }
                for(int j=i+p; (__int64)j+(__int64)(m-1)*(__int64)p<n;j+=p)
                {
                    int y=a[j-p];
                    if(vist1[y])
                    {
                        if(vist2[y]==vist1[y])
                        {
                            ans1--;
                            vist3[y]=0;
                        }
    
                        vist2[y]--;
                        if(vist2[y]==vist1[y])
                        {
                            ans1++;
                            vist3[y]=0;
                        }
                    }
                    y=a[j+(m-1)*p];
                    if(vist1[y])
                    {
                        vist2[y]++;
                        if(vist2[y]==vist1[y])
                        {
                            ans1++;
                            vist3[y]=0;
                        }
                        if(vist2[y]>vist1[y]&&vist3[y]==0)
                        {
                            ans1--;
                            vist3[y]=1;
                        }
                    }
                    if(ans1==ans)
                    {
                        total[sum++]=j;
                    }
                }
                for(int k=0;k<m;k++)
                {
                    vist2[b[k]]=0;
                    vist3[b[k]]=0;
                    ans1=0;
                }
            }
            printf("%d
    ",sum);
            sort(total,total+sum);
            for(int i=0; i<sum; i++)
            {
                if(i==0)
                    printf("%d",total[i]+1);
                else
                    printf(" %d",total[i]+1);
            }
            printf("
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    文件操作函数
    sublime text2 常用快捷键
    过滤掉字段为空的数据
    PHP安装memcache扩展接口步骤
    大数据的逻辑,其实是中医的逻辑
    大数据的逻辑,其实是中医的逻辑
    SPSS输出结果如何在word中设置小数点前面显示加0
    SPSS输出结果如何在word中设置小数点前面显示加0
    掌握4个有效的数据分析要点,切实解决用户痛点
    掌握4个有效的数据分析要点,切实解决用户痛点
  • 原文地址:https://www.cnblogs.com/ziyi--caolu/p/3454077.html
Copyright © 2011-2022 走看看