Prefix Equality(哈希)

题意

给定两个长度为\(N\)的序列\(A = (a_1, a_2, \dots, a_n)\)\(B = (b_1, b_2, \dots, b_n)\)

现在有\(Q\)次询问,每次询问给定两个正整数\(x_i\)\(y_i\),问:
\((a_1, a_2, \dots, a_{x_i})\)构成的集合和\((b_1, b_2, \dots, b_{y_i})\)构成的集合是否相等。

数据范围

\(1 \leq N, Q \leq 2 \times 10^5\)

思路

考虑哈希。

对于每一个数,都将其映射到一个随机数。对于一个集合,将这个集合中所有元素的哈希值之和作为整个集合的哈希值。

如果两个集合的哈希值相等,那么这两个集合相等。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <random>
#include <map>
#include <set>

using namespace std;

typedef unsigned long long ull;

const int N = 200010;

mt19937_64 mrand(random_device{}());

int n, q;
map<int, ull> cnt;
ull ha[N], hb[N];
set<int> cnta, cntb;

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++) {
        int x;
        scanf("%d", &x);
        if(!cnt.count(x)) cnt[x] = mrand();
        ha[i] = ha[i - 1];
        if(!cnta.count(x)) ha[i] += cnt[x];
        cnta.insert(x);
    }
    for(int i = 1; i <= n; i ++) {
        int x;
        scanf("%d", &x);
        if(!cnt.count(x)) cnt[x] = mrand();
        hb[i] = hb[i - 1];
        if(!cntb.count(x)) hb[i] += cnt[x];
        cntb.insert(x);
    }
    scanf("%d", &q);
    while(q --) {
        int x, y;
        scanf("%d%d", &x, &y);
        if(ha[x] == hb[y]) puts("Yes");
        else puts("No");
    }
    return 0;
}
posted @ 2022-05-13 00:32  pbc的成长之路  阅读(97)  评论(0编辑  收藏  举报