CIMOTA 的题

Statement

I_AM_CIMOTA 出了一道数据结构题:

  1. 添加一个操作:把 \([l,r]\) 区间中的数加上 \(x\)
  2. 询问如果我执行了 \([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 上给大家做一做。)

posted @ 2024-08-10 09:38  Laijinyi  阅读(6)  评论(0编辑  收藏  举报