P1253 题解:[yLOI2018] 扶苏的问题
用矩阵把区间加和区间赋值写到一起,懒标记的合成顺序也就清楚了。
这题要同时处理区间赋值、区间加和区间最大值。刚写的时候没想清楚两种修改该怎么合起来,后来受到别人的启发,试着用矩阵推了一遍。
把修改写成矩阵
把值 写成 。加上 ,就是
赋值为 ,就是
区间最大值也能这样更新:所有数加上 ,最大值跟着加;所有数都变成 ,最大值也变成 。因此节点记录 ,合并时取较大值就行。
这里用的是行向量,修改要右乘矩阵。先做 再做 ,合起来就是 ,顺序别反了。代码里的 composition(f, g) 表示先执行 g、再执行 f,对应的也是 。
主要代码
using Info = std::array<i64, 2>;using Function = std::array<i64, 4>;auto mapping = [&](Function f, Info x) -> Info { return Info{x[0] * f[0] + x[1] * f[2], x[0] * f[1] + x[1] * f[3]};};auto composition = [&](Function f, Function g) -> Function { return Function{g[0] * f[0] + g[1] * f[2], g[0] * f[1] + g[1] * f[3], g[2] * f[0] + g[3] * f[2], g[2] * f[1] + g[3] * f[3]};};auto op = [&](Info lhs, Info rhs) -> Info { return Info{std::max(lhs[0], rhs[0]), 1};};auto e = [&]() -> Info { return Info{-inf64, 0};};auto id = [&]() -> Function { return Function{1, 0, 0, 1};};int n, q;std::cin >> n >> q;SegmentTree::LazySegTree<Info, Function, mapping, composition, op, e, id> seg(n, [&](auto ...) { Info x; std::cin >> x[0]; x[1] = 1; return x;});