Sereja ans Anagrams CodeForces - 367B (queue + map)

Sereja has two sequences a and b and number p. Sequence a consists of n integers a1, a2, ..., an. Similarly, sequence b consists of m integers 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 nintegers 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.

Example
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 数组找和 b 数组等长的下标成等差数列的子序列。问等差数列首项 q 的可能的值。

思路:

如果不限定等差数列的长度,那么对于确定的 p , q 取值范围为1,2,3......p;现在限定等差子序列长度为m,则 q 可能为原等差数列的前几项。

所以 :

1.双层循环 外层 q 从1 到 p;内层 j 从 for(ll j = i; j <= n; j+=p) 注意用long long;

2.用队列先进先出的性质,依次存取子等差数列的值,存够m个值后,比较一下 队列里下标对应a[]的值与b[] 的数是否一致,具体方法见3,一致,则吐出队首的下标,q数目加1,不一致丢弃;

3 用 map 存关系,从而确定队列里存的下标确定的a[]里的值,是否能和b[]里一致,map 可以直接判断是否相等如mp1 == mp2,但是如果mp [x] == 0 了 记得mp.erase(x),否则影响mp1 == mp 的比较。

#include <map>
#include <cstdio>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;

typedef long long ll;

const int maxn = 2e5 + 10;

int a[maxn],b[maxn],ans[maxn];
map <int ,int> mpa,mpb;

int main()
{
   int n,m,p;
   scanf("%d%d%d",&n,&m,&p);
   for(int i = 1; i <= n ; i++)
        scanf("%d",&a[i]);
   for(int i = 1; i <= m; i++)
    {
          scanf("%d",&b[i]);
          mpb[b[i]] ++ ;
    }
    int k = 0;
    for(int i = 1; i <= p; i++)
    {
          queue <int > qu;
          mpa.clear();
          for(ll j = i; j <= n; j += p)
          {
                 mpa[a[j]] ++;
                 qu.push(j);
                 if(qu.size() == m)
                 {
                        int x = qu.front();
                        if(mpa == mpb)
                            ans[k++] = x;
                        qu.pop();
                        mpa[a[x]] --;
                        if(mpa[a[x]] == 0)
                              mpa.erase(a[x]);
                 }
          }
    }
    sort(ans,ans+k);
    printf("%d\n",k);
    for(int i = 0; i < k; i++)
         printf("%d ",ans[i]);
    printf("\n");
}


这段代码实现了一个数列生成的功能,接受四个整数作为输入,分别表示数列中1的个数、0的个数、-1的个数和数列长度k。根据这些输入,代码输出一个长度为k的数列,满足以下条件: - 数列中1的个数等于输入的numOne; - 数列中0的个数等于输入的numZero; - 数列中-1的个数等于输入的numNegOne; - 数列中相邻两项之差的绝对值不超过1。 代码中的max函数用于求两个数的最大值,主函数main中定义了4个整型变量,分别为numOne、numZero、numNegOne和k。接下来使用scanf函数读入输入的4个整数。 定义了三个计数变量cntOne、cntZero和cntNegOne,分别表示当前已生成数列中1的个数、0的个数和-1的个数。定义ans变量表示当前生成的数列中最后一项和第一项的差值。初始值为0。 使用while循环,直到生成的数列长度达到k为止。循环中使用条件语句判断当前可以生成哪些数。如果numOne的值大于0,则生成1,并将cntOne加1,numOne减1。如果numNegOne和numZero的值都大于0,则生成-1和0,将cntNegOne、cntZero分别加1,numNegOne和numZero分别减1。如果numNegOne的值大于等于2,则生成-2,将cntNegOne加2,numNegOne减2。如果numZero的值大于等于2,则生成2个0,将cntZero加2,numZero减2。如果无法继续生成数列,则跳出循环。 最后使用printf函数输出ans的值,即生成的数列中最后一项和第一项的差值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值