CIMOTA 的题
Statement
I_AM_CIMOTA 出了一道数据结构题:
- 添加一个操作:把 \([l,r]\) 区间中的数加上 \(x\)。
- 询问如果我执行了 \([l,r]\) 区间的操作,\(pos\) 这一个点的值会变为多少。
Solution
在线做法:可持久化线段树,标记永久化的话比较方便。
离线做法:分别在时间 \(l-1,r\) 挂一个 \(pos\) 的询问以及 \(-1,1\) 的贡献系数. 然后扫一下.
在线做法 2:树套树:
- 把每个操作看成一个元素 \((l_i,r_i,x_i)\).
- 每次询问相当于在 \([l,r]\) 区间的元素中,对于每个 \(i\) 若 \(pos\in[l_i,r_i]\),那么答案 += \(x_i\),求最终的答案.
- 众所周知这可以树套树,外层维护操作序列、内层维护序列值;也可以外层每次 \([l_i,r_i]\) 插入元素,内层维护在 \(id\) 单点加 \(x_i\),查询时外层单点路径查、内层区间和
离线做法 2:按时间分治:
- 每个操作对询问的贡献独立,且可转化为前缀和相减的形式,故可以分治
离线做法 3:
- 类似线段树分治,每个节点维护该时间区间内询问了哪些 \(pos\),此时树上有 \(m\log m\) 个询问.
- 同时每个点维护该时间区间内的修改情况,也就是维护若干 add 标记不同的连续区间.
- 每次添加操作就找到当前时间到根一路上的所有点进行插入,每个点插入一个 \([l,r,add]\) 的元素最多增加两个区间。
- 如果子树被塞满了就应用修改并回收空间,这样空间是 \(O(n)\).
在线做法 3:二进制分组
在线做法 4:分块
....
(有时间出个数据搬到 OJ 上给大家做一做。)