珂朵莉树/颜色段均摊 ODT
set写法
结构体保存这个颜色段的
split 分割操作
这里 split(pos) 表示在 pos 前分割. 返回pos后面的一个颜色段.
用 lower_bound 查找大于等于 pos 的分段, 查找后判断:
- 这个段的
正好是 pos: 无需处理直接返回. - 其他情况: 此时
pos在查找到的分段的前一个分段内, 记录前一个分段的, , 并删除前一个分段, 再创建两个块, 分别是 和 , 权值不变. 然后直接返回后者的迭代器.
assign 赋值操作
这里 assign(l,r,x) 表示将 x.
先分割 il 和 ir, 删除 il 到 ir-1 的全部颜色快, 注意 vector 的 erase 是 [) 区间, 所以可以直接调用 erase(il,ir). 然后再创建一个 x 的块.
这里有一个注意点: 要先切割
如果先切割
例题: P3740 [HAOI2014] 贴海报
这个就是一个最基础的ODT, 按照题意操作,每一站海报就是一个颜色. 统计答案时, 把存在的每一个颜色加入一个 set 中, set 的大小即为答案. 注意判断是否有 0 的颜色, 即没被贴到的区域, 有的话答案要-1.
参考代码
1 | |
map 写法
相较于 set 写法, map 稍微简单一些. 结构体的定义与 set 写法相同. 下文函数表示的含义不变.
map 的 key 对应这个颜色段的左端点 value 记录这个颜色段的数据.
split 分割操作
首先我们需要找到左端点小于等于 pos 的颜色段. 考虑这样子操作: prev(mp.upper_bound(pos)). 我们便找到了这个颜色段. 找到这个颜色段的目的是获取分割后的颜色信息. 然后使 mp[pos]= 查找到的颜色即可. 由于 map 的便捷性, 我们无需返回迭代器.
assign 赋值操作
先分割
例题: P1840 Color the Axis
依旧是一道珂朵莉树板子题, 按照题意操作即可.
参考代码
1 | |
链表写法
过于麻烦
例题: C. Willem, Chtholly and Seniorious
题目大意: 给你一个数列, 你需要对给定的区间
- 把这些数字的加上
- 把这些数字设为
- 输出区间第
小数 - 输出所有数的
次幂之和模 , 即
看似不好做, 但是, 由于第二个操作类型的存在, 一定存在一些相邻的数相同, 我们便可以使用珂朵莉树维护.
操作1
分割后操作即可.
操作2
直接使用 assign 操作即可.
操作3
存储这一部分区间的值和长度, 排序后便利即可.
操作4
分割后, 从左到右对区间进行计算求和即可.
注意
快速幂过程中注意开 __int128, 否则可能出现炸long long.
参考代码
1 | |