题目
长度为n(n<=3e5)的数组,q(q<=3e5)次操作,操作分两种,
1. 输入i x(x<=1e9),将ai改成x
2. 输入l r k(1<=k<=n),询问对于在[l,r]内出现的每种数,其在[l,r]内的出现次数是不是均为k的倍数
思路来源
gzchenben的讲解
jjleo的代码
题解
随机化哈希,人尽皆知典中典
k的倍数,区间每种数的出现次数很难维护,考虑概率&哈希
对于输入的ai,先将其哈希映射到另一个数上,然后考虑按二进制位拆,
如果对于二进制的每一位,其在[l,r]内的和都是k的倍数,我们就认为答案是Yes,
这样错误的概率,对于某一位来说,在k=2时,是1/2,
因为随机哈希,可能将两个二进制这一位原本不同的数,映射成相同了,
但是,控制位数足够多后,这样询问出错的概率就很低了,
考虑到3e5组样例,实际后台可能有100个case,3e8左右,所以30位≈1e9不一定行,
这里控制位数M在35-40左右即可
不被hack掉的tips
1. 哈希是完全随机的(如mt19937_64)
2. 对于不同的ai,哈希出来的数不重复
心得
mt19937_64用起来很方便,实际控制M=64保险,但M=35-40就够用了,1/(2^35)的概率很低了
放一个抄来的随机数生成的方法,主要这题需要尽可能保证每次gen的随机数不重复
update:unordered_map被卡了,赶紧改回map
int gen(){
static int o=4354347;
o=(1ll*o*1926

最低0.47元/天 解锁文章
691

被折叠的 条评论
为什么被折叠?



