CF368D(处理数字出现次数)

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

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

Sereja has two sequences a and b and number p. Sequence a consists of n integers a1, a2, ..., an. Similarly, sequence b consists of mintegers b1, b2, ..., bm. As usual, Sereja studies the sequences he has. Today he wants to find the number of positions q (q + (m - 1)·p ≤ nq ≥ 1), such that sequence b can be obtained from sequence aq, aq + p, aq + 2p, ..., aq + (m - 1)p by rearranging elements.

Sereja needs to rush to the gym, so he asked to find all the described positions of q.

Input

The first line contains three integers nm and p (1 ≤ n, m ≤ 2·105, 1 ≤ p ≤ 2·105). The next line contains n integers a1a2...an (1 ≤ ai ≤ 109). The next line contains m integers b1b2...bm (1 ≤ bi ≤ 109).

Output

In the first line print the number of valid qs. In the second line, print the valid values in the increasing order.

Sample test(s)
input
5 3 1
1 2 3 2 1
1 2 3
output
2
1 3
input
6 3 2
1 3 2 2 3 1
1 2 3
output
2
1 2

题意:有一个a[n]的数组,要从找个i得m个数字a[i],a[i+p],a[i+2*p]......a[i+(m-1)*p]在另一个数组b[m]中全部找到,并且数字个数不多不少。

思路:现将a数组离散化,然后滚动的去找这m个数字。对于ans的判断靠b数组中元素的种类数来看(详见代码)。

代码:

#include
#include
#include
#include
#include
using namespace std;
//#define M 11111
int a[200010],c[200010];
vector ans;
int erfen(int ll,int rr,int ans)  //二分函数
{
    while(ll<=rr)
    {
        int mid=(ll+rr)/2;
        if(c[mid]>ans)
            rr=mid-1;
        else  ll=mid+1;
    }
    return rr;
}
int main()
{
    int i,j,h,k,n,m,p,ans2,ans3;
    int b[200010]={0};
    scanf("%d%d%d",&n,&m,&p);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        c[i]=a[i];
    }
    sort(c+1,c+1+n);  //利用二分离散化
    for(i=1,k=0;i(n-1)/p) {puts("0");return 0;}
    for(i=1;i<=p;i++)
    {
        ans3=0;int vis[200010]={0};
        for(j=i;j<=n;j+=p)
        {
            if((j-i)/p>=m)
            {
                if(vis[a[j-m*p]]-1==b[a[j-m*p]]) ans3++;  //当你删去一个该元素后发现该元素个数与b数组中该元素个数相等,那么ans3++
                else if(vis[a[j-m*p]]==b[a[j-m*p]]) ans3--;  //当你还未删去一个该元素时发现该元素个数与b数组中该元素个数相等,那么ans3--
                vis[a[j-m*p]]--;  //标记数组中的元素个数值一定要改变
            }
            if(vis[a[j]]+1==b[a[j]]) ans3++;  //当你加上一个该元素后发现该元素个数与b数组中该元素个数相等,那么ans3++
            else if(vis[a[j]]==b[a[j]]) ans3--;  //当你还未加上一个该元素时发现该元素个数与b数组中该元素个数相等,那么ans3--
            vis[a[j]]++;  //标记数组中的元素个数值一定要改变
            if(ans3==ans2) ans.push_back(j-(m-1)*p);  //如果ans3与ans2相等,则说明这个是对的
        }
    }
    printf("%d\n",ans.size());
    sort(ans.begin(),ans.end());
    for(i=0;i


你可能感兴趣的:(杂项)