传送门
这道题要求我们对于非常多的询问回答[l,r]、[L,R]这样两个区间内A、B数组中各个数的出现次数是否相同。
看到这道题似乎想到了刚开始学编程的时候就想过的一个问题(bushi,那就是我能不能直接用,例如说这段区间和是否相同,或者说这段区间乘积之类的是否相同来判断这个区间各个数出现次数是否相同。这道题就给了我答案,那就是利用随机化哈希,即,我们对每一个出现在A、B数组中的数都将它变成一个对应的随机的数,然后对于每个询问的区间来看各自的区间和是否相同即可。注意第一次看到这种做法可能觉得非常荒谬,因为它让人觉得跟我们直接求前缀和来判断相等没有什么两样。这其实就是随机化算法的特点,当这个算法正确率已经达到99.9%甚至往上,我们就可以认定这个做法是正确的。这道题正是如此,我们在\(2^{32}\)之内随机\(10^{5}\)量级个数出现两个区间和相同的概率是极小的,而题目给的A、B数组都是关于N的一个排列,这样出现两个区间和相同的概率是很大的。
代码如下:
#include<bits/stdc++.h>
using namespace std;
long long t;
const long long mod = 1e9 + 7;
const long long N = 2e5 + 10;
long long n,qq;
long long a[N],b[N];
long long s1[N],s2[N];
map<long long,long long> q;
void solve() {
mt19937 myrand(time(nullptr));
cin >> n >> qq;
for(long long i = 1;i <= n;i++) {
cin >> a[i];
if(!q[a[i]]) q[a[i]] = myrand() % mod;
a[i] = q[a[i]];
s1[i] = s1[i-1] + a[i];
}
for(long long i = 1;i <= n;i++) {
cin >> b[i];
if(!q[b[i]]) q[b[i]] = myrand() % mod;
b[i] = q[b[i]];
s2[i] = s2[i-1] + b[i];
}
for(long long i = 1;i <= qq;i++) {
long long l,r,ll,rr;
cin >> l >> r >> ll >> rr;
if(s1[r] - s1[l-1] == s2[rr] - s2[ll-1]) cout << "Yes\n";
else cout << "No\n";
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
t = 1;
while(t--) solve();
return 0;
}
标签:s2,s1,long,ABC367F,随机化,这道题,哈希,区间
From: https://www.cnblogs.com/lwiwi/p/18664799