倍增值域分块
CF702F T-Shirts
考虑将 \(q_i\) 从大到小排序, 将 \(a_i\) 从小到大排序, 并维护一个 \(b_i\) 数组表示答案, 我们遍历 \(q_j\) 数组, 每次是将 \(a_i\) 数组中 \(a_i \geq c_j\) 的全部减 \(c_i\), 然后 \(b_i\) 加 1 。 考虑用平衡树维护 \(a_i\), split 一下, 右区间树打一个 tag, 但考虑打完 tag 合并不起来, $ [c_i, 2c_i] $ 的减去 \(c_i\) 后左右区间树值域会有重叠, 考虑把这个区间的数暴力取出来, 减完后一个一个加回平衡树, 考虑这些数被操作后起码减半, 所以可以有均摊的复杂度 \(O(logV)\)。 总时间复杂度 \(O(nlognlogV)\)。
P7447 [Ynoi2007] rgxsxrs
考虑这里的数不会减半, 并且要访问区间, 我们不能暴力, 所以来个数据结构多维护一维表示区间, 考虑按值域倍增分块为 \([0, 1), [1, 2), [2, 4), [4, 8)...\) 。 每个值域开一棵线段树, 然后维护最大值最小值。 考虑将 $\geq x $ 的减去 \(x\), 某个值域中的数减去 \(x\) 后, 不处于该值域, 则暴力加入其他值域, 考虑最多下降 \(logV\) 次, 每次从线段树中取出加入 \(logn\), 总复杂度 \(O(nlognlogV)\)。 最大值最小值用来分讨和应对询问。
P9069 [Ynoi Easy Round 2022] 堕天作战
考虑转化为 $ < a$ 的减 \(a\), 和 \(> a\) 的减 \(a\), 大于 \(a\) 和上题一样, 然后 \(< a\) 的考虑如果变成负数就再也不会被减, 并且如果 \(< a\) 再减去 \(a\), 就一定会变成负数, 所以直接暴力, 均摊是 \(O(1)\) 的, 在对负数值域开一棵线段树即可。时间复杂度 \(O(nlognlogV + nlogn)\)。
P4587 [FJOI2016]神秘数
典中典
2019ICPC徐州 H - Yuuki and a problem
就是上一道题加强版。 倍增值域分块, 每个值域块拿线段树限制区间 \((l, r)\) , 可以搞到两个 \(log\)。 这样考虑上一题不用修改就可以用 RMQ,\(O(1)\) 查询做到一个 \(log\)。