CF718C Sasha and Array
重点:
矩阵乘法 a × ( b + c ) = a b + a c a\times(b + c) = ab + ac a×(b+c)=ab+ac。
而且矩阵乘法是有结合律的: a × b × c = a × ( b × c ) a \times b \times c = a\times (b\times c) a×b×c=a×(b×c)
但是 没有 \color{red}\text{没有} 没有 交换律!!
发现这个下标的信息不是很好维护我们考虑将其放到矩阵里面进行维护。
也就是说我们需要维护一个权值和还有一个转移的矩阵。
对于一个区间加的操作对于整体区间都可以乘上一个转移矩阵。
我们考虑计算答案的时候直接维护一个答案矩阵即可。
具体来说不妨设初始矩阵为:
[ f i − 1 , f i ] \left[ \begin{matrix} f_{i - 1}, f_i \end{matrix} \right] [fi−1,fi]
那么转移矩阵就是:
[ 0 1 1 1 ] \left[ \begin{matrix} 0 & 1 \\ 1 & 1 \end{matrix} \right] [0111]
我们分别维护这两个量,每次下传标记的时候更新即可。
题外话:
我想的时候想到了矩阵,但是不知道为什么就是搞不懂要怎么维护。思路历程是这样的:我们考虑维护整个答案的矩阵,如果整体修改很好办,但是如果部分修改呢?
其实这个就和普通的线段树维护一样,只需要考虑如何合并左右两个节点的信息而已。
对于矩阵的信息我们可以直接加,也就是 c a + c b ca + cb ca+cb 的形式。
但是如果区间修改的话,一开始没有想到好的办法,其实本质上就是 c × ( a + b ) = c a + c b c \times (a + b) = ca + cb c×(a+b)=ca+cb。所以直接对于之前的答案矩阵进行乘法即可。
#include <bits/stdc++.h>
using namespace std;
//#define Fread
#define Getmod
#ifdef Fread
char buf[1 << 21], *iS, *iT;
#define gc() (iS == iT ? (iT = (iS = buf) + fread (buf, 1, 1 << 21, stdin), (iS == iT ? EOF : *iS