P9212 「蓬莱人形」简要做法
题意简述
给定一个长为 \(n\) 的序列 \(a\),\(q\) 次询问,每次询问给定 \(l,r,x,y,m\),让你求满足有多少个 \(i \in [l,r]\) 满足 \((a_i+x)\bmod m<(a_i+y)\bmod m\),可以认为 \(n,q\) 同阶。
题目做法
这个真的太模板了吧。
首先注意到当 \(x < y\) 时,你的询问是在查询 \(a_i + x\) 与 \(a_i + y\) 都比 \(m\) 大或都比 \(m\) 小的 \(i\) 的个数,等价于两段值域数点,当 \(x > y\) 时,你的询问是查询 \(a_i + x\) 大于 \(m\) 而 \(a_i + y\) 小于 \(m\) 的 \(i\) 的个数,也是一段值域数点。
然后看到是在模 \(m\) 意义下,其中 \(m\) 每次询问给定,那就很难想不到根号分治,于是分成两部分。
- 当查询的 \(m\) 小于 \(\sqrt n\) 时:
考虑预处理出 \(b_{i,j}\) 表示 \(a_j\) 在模 \(i\) 意义下值,然后分块。
如果询问落在散块显然可以直接暴力,对于落在整块的询问可以统计 \(f_{i,j,k}\) 表示第 \(j\) 个块在模 \(i\) 意义下前 \(k\) 个数出现了多少次,询问对于每个块差分一下即可,当然你可以将 \(j\) 这一位做前缀和,但是没有意义。
- 当查询的 \(m\) 大于 \(\sqrt n\) 时:
你直接把询问拆成 \(\mathcal O(n \sqrt n)\) 个,然后做二维数点。
这个二位数点是有 \(\mathcal O(n)\) 次修改,\(\mathcal O(n \sqrt n)\) 次询问的,你直接使用 \(\mathcal O(\sqrt n) - \mathcal O(1)\) 的分块平衡一下就好了。

浙公网安备 33010602011771号