分块基本思想:
- 将长度为 \(n\) 的序列划分成 \(\sqrt n\) 块,每块的元素个数为 \(\sqrt n\)。
- 维护 \(pos[i]\) 表示下标 \(i\) 的元素所在块的编号,维护 \(L[i]\) 和 \(R[i]\) 表示第 \(i\) 块的起始下标和中止下标。
- 每个块维护相应的信息,比如区间和等。
- 维护块的标记 \(tag[i]\),表示第 \(i\) 个块的修改信息
- 对于一次询问 \([x, y]\):
5. 1. 若 \(x\) 和 \(y\) 在同一个块中,则暴力枚举找答案,时间复杂度 \(O(\sqrt n)\)。
5. 2. 若 \(x\) 和 \(y\) 不在同一个块,分为 \(3\) 部分处理:
5. 2. 1. \(x\) 所在块,暴力枚举, \(O(\sqrt n)\)。
5. 2. 2. \(y\) 所在块,暴力枚举,\(O(\sqrt n)\)。
5. 2. 3. \(x\) 和 \(y\) 中间完整的块,整块枚举, \(O(\sqrt n)\)。
5. 3. 询问时不论是完整的块还是不完整的块,都要读取 \(tag[i]\)。 - 对于一次修改 \([x, y]\),增加 \(val\)。方式与询问类似。
6. 1. 枚举完整的块时,修改 \(tag[i]\),否则不改动。