【题目】教主的魔法

这次竟然分到一道板题……

题目大意

给出一个长度为 n n n的序列,每个数字一开始都是不超过 1000 1000 1000的正整数。下面进行两种操作:

  • M l r w:把闭区间 [ l , r ] [l,r] [l,r]内的数字的值全部加上一个整数 w w w 1 ⩽ w ⩽ 1000 1\leqslant w\leqslant 1000 1w1000
  • A l r c:询问闭区间 [ l , r ] [l,r] [l,r]内有多少个数大于等于 c c c 1 ⩽ c ⩽ 1 0 9 1\leqslant c\leqslant 10^9 1c109

n ⩽ 1000000 n\leqslant 1000000 n1000000 Q ⩽ 3000 Q\leqslant 3000 Q3000


思路

常见的区间问题中区间长度 n n n和操作次数 Q Q Q范围都是相当的,而本题 Q Q Q小得有点奇怪,只相当于 n \sqrt n n 。这暗示我们可以用分块。

由于第二个操作涉及到大小比较,除了给出的 A A A序列外,另外维护一个序列 B B B,保证 B B B中每一块内的数字都是有序的。然后就可以愉快的分块了。

区间修改

对于区间两端不包含某个块的部分,暴力对每个值加 w w w。加完后维护一下 B B B序列中对应块的数字(复制后重新排序)。
对于被区间完全覆盖的块,用一个 a d d add add标记记录每一块被整体增加的值。
时间复杂度 O ( n log ⁡ 2 n ) O(\sqrt n\log_2n) O(n log2n)

区间查询

对于区间两端的部分,同样暴力枚举,记录大于等于 c c c的数的个数,但注意要加上对应块的 a d d add add标记。
对于被区间完全覆盖的块,在 B B B序列的对应块内用lower_bound找出第一个大于等于 c − a d d c-add cadd的位置,然后可以据此计算出该块内大于等于 c c c的数的个数。
时间复杂度 O ( n log ⁡ 2 n ) O(\sqrt n\log_2n) O(n log2n)

……然后就完了。注意区分数字的序号和块的序号,以及最后一个块不足 n \sqrt n n 需要特判。

你可能感兴趣的:(思想技巧)