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 Round #215 (Div. 2) D. Sereja ans Anagrams的更多相关文章

  1. Codeforces Round #215 (Div. 1) B. Sereja ans Anagrams 匹配

    B. Sereja ans Anagrams Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset ...

  2. Codeforces Round #215 (Div. 2) B. Sereja and Suffixes map

    B. Sereja and Suffixes Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset ...

  3. Codeforces Round #215 (Div. 2) C. Sereja and Algorithm

    #include <iostream> #include <vector> #include <algorithm> #include <string> ...

  4. Codeforces Round #215 (Div. 2) B. Sereja and Suffixes

    #include <iostream> #include <vector> #include <algorithm> #include <set> us ...

  5. Codeforces Round #215 (Div. 2) A. Sereja and Coat Rack

    #include <iostream> #include <vector> #include <algorithm> using namespace std; in ...

  6. Codeforces Round #215 (Div. 2) D题(离散化+hash)

    D. Sereja ans Anagrams time limit per test 1 second memory limit per test 256 megabytes input standa ...

  7. Codeforces Round #215 (Div. 1)

    A Sereja and Algorithm 题意:给定有x,y,z组成的字符串,每次询问某一段s[l, r]能否变成变成zyxzyx的循环体. 分析: 分析每一段x,y,z数目是否满足构成循环体,当 ...

  8. Codeforces Round #223 (Div. 2) E. Sereja and Brackets 线段树区间合并

    题目链接:http://codeforces.com/contest/381/problem/E  E. Sereja and Brackets time limit per test 1 secon ...

  9. Codeforces Round #223 (Div. 2)--A. Sereja and Dima

    Sereja and Dima time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...

随机推荐

  1. 树莓派进阶之路 (005) - 树莓派Zsh安装脚本(原创)

    zsh.sh #!/bin/bash cd #安装zsh sudo apt-get install zsh #查看zsh cat /etc/shells #更改zsh chsh -s /bin/zsh ...

  2. win7系统部分软件显示乱码怎么办

    用了Win7以后,发现有的中文软件打开后,在界面上出现很多文字乱码,之前这个软件在XP上用过,一直都是中文的,怎么到Win7上,就显示乱码了. 到网上一查,发现很多网友都有同样问题,经过一番查找,找到 ...

  3. Error 25007.初始化合成时发生错误。安装程序无法使用 LoadLibraryShim() 加载合成。

    安装“Microsoft .NET Framework 2.exe”报错如下: c:\windows\microsoft.net\framework\...类似这种错误都因 .NET Framewor ...

  4. 【SqlServer】聚集索引与主键、非聚集索引

    目录结构: contents structure [-] 聚集索引和非聚集索引的区别 聚集索引和主键的区别 主键和(非)聚集索引的常规操作 聚集索引.非聚集索引在SqlServer.MySQL.Ora ...

  5. 【SqlServer】Sql Server 支持的数据类型

    在计算机中数据有两种特征:类型和长度.所谓数据类型就是以数据的表现方式和存储方式来划分的数据的种类.    在SQL Server 中每个变量.参数.表达式等都有数据类型.系统提供的数据类型分为几大类 ...

  6. 【MyBatis】MyBatis之如何配置

    1,MyBatis简介 MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索.MyBatis 使用简 ...

  7. 【struts2】预定义拦截器

    1)预定义拦截器 Struts2有默认的拦截器配置,也就是说,虽然我们没有主动去配置任何关于拦截器的东西,但是Struts2会使用默认引用的拦截器.由于Struts2的默认拦截器声明和引用都在这个St ...

  8. Html中 <tr> 标签的隐藏与显示

    TR标签的隐藏与显示:block(显示)和none(隐藏) <tr  style="display:none"> <tr id="sample" ...

  9. 利用 T-sql 的从句 for xml path('') 实现多行合并到一行, 并带有分隔符

    T-sql 有一个for xml path('')的从句能把多行结果合并到一行,并成为xml 格式 比如有一张表tb有两列,其格式和数据为: id value—————1 aa1 bb2 aaa2 b ...

  10. 设计模式C++实现——模板方法模式

    模式定义: 模板方法模式在一个方法中定义了一个算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类能够在不改变算法结构的情况下,又一次定义算法中的某些步骤. 模板就是一个方法.更详细的说.这种方法将 ...