Codeforces 367B Sereja ans Anagrams 详细题解(map应用+维护长度)

54 篇文章 0 订阅
42 篇文章 0 订阅

B. Sereja ans Anagrams 
time limit per test1 second 
memory limit per test256 megabytes 
inputstandard input 
outputstandard 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 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 ≤ n; q ≥ 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 n, m and p (1 ≤ n, m ≤ 2·105, 1 ≤ p ≤ 2·105). The next line contains n integers a1, a2, …, an (1 ≤ ai ≤ 109). The next line contains m integers b1, b2, …, 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.

Examples 
input 
5 3 1 
1 2 3 2 1 
1 2 3 
output 

1 3 
input 
6 3 2 
1 3 2 2 3 1 
1 2 3 
output 

1 2



题意:给定n个元素的序列a[]和m个元素的序列b[],让你找到一个q使得a[q]、a[q+p]、…a[q+(m-1)*p]构成序列b。问你所有的q。

思路:i、i+p、i+2*p肯定构成一条长链,枚举链的起点,用pre,suf来维护元素的进出跟长度,每当里面有m个元素,用map判定是否满足。

这题学到了map可以直接 == 比较的。。。唉。。菜。。。set也可以直接比较的。。另外,这题复杂度是On的。。虽然两个for但是On的,因为第一个for枚举到p,是枚举起点,没必要枚举p往后的,p往后的每次+p都是重复之前的。。第二个for从i开始每次+p,一直到最后,其实会发现每个元素都只访问了一遍。。。这题也可以用队列维护长度

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <map>
using namespace std;
const int maxn = 2e5 + 5;
int n, m, a[maxn], p, ans, ansl[maxn];
int main()
{
    scanf("%d%d%d", &n, &m, &p);
    for(int i = 1; i <= n; i++)
        scanf("%d", &a[i]);
    map<int, int> b;
    int num;
    for(int i = 1; i <= m; i++)
    {
        scanf("%d", &num);
        b[num]++;
    }
    int index = 1, pre, suf;
    ans = 0;
    for(int i = 1; i <= p; i++)
    {
        map<int, int> match;
        pre = suf = i;
        for(int j = i; j <= n; j += p)
        {
            int id = i+(pre-i)*p;
            if(suf-pre < m)
            {
                suf++;
                match[a[j]]++;
            }
            if(suf-pre == m) //相等的时候,先比较这一段跟b是不是相同的,然后pre往前走,suf往后走
            {
//                cout << pre << ' ' << suf << endl;
//                cout << match[1] << ' ' << match[2] << ' ' << match[3] << endl;
                if(match == b) //两个map可以直接==比较
                {
                    ansl[index++] = id;
                    ans++;
                }
                match[a[id]]--;
                if(match[a[id]] == 0) match.erase(a[id]); //直接比较 等于0 要把这个元素删掉
                pre++;
            }
        }
    }
    sort(ansl+1, ansl+index);
    printf("%d\n", ans);
    for(int i = 1; i < index; i++)
    {
        printf("%d%c", ansl[i], i == index-1 ? '\n' : ' ');
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值