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\n");

            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\n",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("\n");

    }

    return 0;

}

 

你可能感兴趣的:(codeforces)