题意
给定两个长度为\(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;
}