A
直接做难做,考虑按位异或,则可以将一个 int 拆成 32 位二进制数,用线段树 \(sgt[u][i]\)维护在第 \(i\) 位区间中 \(1\) 的个数,这样的复杂度是普通线段树的复杂度乘上 32 的常数。
启发:如果直接操作不具有传递性,考虑转化为有传递性的操作,在这题是将一整个数异或转化为按位异或。
B
我们发现取模不具有传递性,结合上题的启发,我们发现非常难以转换成有传递性的操作。不过我们有一个非常好的发现:\(a \bmod m < \frac{a}{2} \ \ (a\ge m)\),我们发现这样的取模操作最多只有 \(\log_2\) 次,因为当 \(a<m\) 这样取模完没有任何影响,于是我们可以考虑用线段树维护区间最大值和区间和,如果区间最大值大于模数,递归往下暴力做,否则直接剪掉,复杂度是均摊 \(O(n \log n \log V)\)。
启发:遇到这种减小速度比较快的,可以考虑暴力修改 + 剪枝。
相关题目:类似的题还有 这道 和 进阶版,这两道可以考虑极差(最大值最小值的差)。
C
直接排序这东西很难刻画,但我们发现这东西的值域很小,只有 26,我们将其转化成计数与区间覆盖,具体来说,线段树节点结构体 \(node\) 存的是字符集,记录该区间每种字符出现次数,区间修改时,先获得当前 \(l\sim r\) 的节点信息,再根据升序还是降序依次区间覆盖,如将 \(l\sim l + cnt_a - 1\) 覆盖成 \(a\),复杂度是线段树复杂度再乘上 26 的常数。
启发:遇到这种值域很小的,可以考虑将其转化成计数,再用线段树相关操作处理。
加强题目:将值域扩大成 \(10^9\),询问不变 或者 询问变成最后单点询问(离线),对于最后的单点询问,我们可以转化成二分答案,将 \(<\) 二分枚举的值变成 0,将 \(>\) 的变成 \(1\)。这样又变成 \(O(n \log^2 n)\)
D
排序是与大小关系相关,于是可以考虑依次判断与 \(b_i\) 值相等的 \(a_{pos}\) 能否移动到 \(i\),\(a_{pos}\) 能移动到 \(i\) 的必要条件是 \(\min\{a_1\sim a_{pos}\} \le a_{pos}\),线段树维护即可,不要忘记还要将 \(a_{pos}\) 赋值为 \(\infty\)。
启发:将排序转化成大小关系相关,用数据结构维护。
E
线段树节点转为维护不匹配的 左括号个数和右括号个数,计算时简单容斥。
启发:直接维护题目要求的可能不容易,转化一下可能好做。
G
简单树状数组上二分。
H
把交换的左右端点单独拎出来,对他们计算逆序对,再分别统计他们对其他数的贡献。
I
先转化成计算多少个区间没有覆盖任何点,那么这种区间应该是在 \([p_{i-1}+1,p_i-1]\) 之间


即求 \(L\le l\le r\le R\) 中 \(l,r\) 的个数,那么二维偏序来做,按 \(l\) 从大到小排序,再按 \(r\) 从小到大排序,用树状数组维护右端点即可。
K
线段树维护模5的余数,\(push_up\) 注意一下。
