0%

2026 杭电春季联赛 3——1009-时空回溯(向下取整除法的性质)

题目大意

题目描述

给定一个长度为 nn 的数组 AA 以及一个阈值 mm。你需要维护这个数组并支持以下两种操作,共执行 QQ 次:

  • 1 L R X:将区间 [L,R][L, R] 内的所有元素减去 XX(即对于 LiRL \le i \le R,执行 AiAiXA_i \leftarrow A_i - X)。

  • 2 L R:将区间 [L,R][L, R] 内的所有元素右移一位(相当于除以 22 向下取整,即对于 LiRL \le i \le R,执行 AiAi2A_i \leftarrow \lfloor \frac{A_i}{2} \rfloor)。

在每一次操作结束后,如果整个数组中存在至少一个元素小于等于阈值 mm,则会触发一次“时空回溯”:

  1. 全局重置次数 kk 的值增加 11

  2. 整个数组 AA 立即恢复为最开始的初始状态。

要求在处理完所有给定的 QQ 次操作后,输出最终的重置次数 kk(初始时 k=0k=0)。

数据范围

  • 数据组数 T10T \le 10

  • 1n,Q1051 \le n, Q \le 10^5

  • 0m<2300 \le m < 2^{30}

  • 初始数组满足 m<Ai<230m < A_i < 2^{30}

  • 对于操作 1:1LRn1 \le L \le R \le n0X<2300 \le X < 2^{30}

  • 对于操作 2:1LRn1 \le L \le R \le n

样例输入

1
2
3
4
5
6
1
3 1 3
5 4 6
1 1 2 4
2 2 3
1 1 3 5

样例输出

1
2

样例解释

初始时数组为 [5,4,6][5, 4, 6],阈值 m=1m = 1,重置次数 k=0k = 0

  • 11 次操作(1 1 2 4):对区间 [1,2][1, 2] 的元素减去 44,数组变为 [1,0,6][1, 0, 6]。此时存在元素(1100)小于等于阈值 11,触发回溯。重置次数 k1k \leftarrow 1,数组重置为初始状态 [5,4,6][5, 4, 6]

  • 22 次操作(2 2 3):对区间 [2,3][2, 3] 的元素右移一位,数组变为 [5,2,3][5, 2, 3]。此时数组中所有元素均大于 11,不触发回溯。

  • 33 次操作(1 1 3 5):对区间 [1,3][1, 3] 的元素减去 55,数组变为 [0,3,2][0, -3, -2]。此时存在元素小于等于阈值 11,触发回溯。重置次数 k2k \leftarrow 2,数组重置为初始状态 [5,4,6][5, 4, 6]

所有操作执行完毕,最终的重置次数 kk22

思路讲解

gemini 的这个数学功底比较好,直接合并了这个位移操作和这个减法操作。

PDF

image

这个向下嵌套性质不是那么容易可以看出来的,那么我让 gemini 写了一个完整的,直观的,而且也是非常严谨的这个解释,还是非常好的:

image

不过我们是用题解的这个做法

image

我们可以维护一个这个标记数组,

AC代码

AC
https://acm.hdu.edu.cn/contest/view-code?cid=1199&rid=17893

心路历程(WA,TLE,MLE……)

PDF

一般来说,一个线段树只应该有一个 merge 函数,因为我们的 merge 是 static 的,我们的逻辑也是用 merge 从子节点中完全重新推出父节点

vector clear() 函数减少内存的重新分配(保留 capacity),进而加快速度

类似于 t.op_ls[i].type,这样子比较复杂的东西,可以使用引用,重命名为 t_op_ls[i].type,这样子书写的时候可以少一层,可以减少写错的可能性

注意特殊操作的范围,不一定就局限在【l,r】了,可能是全局操作【1,N】。