LibreOJ #2980 [THUSCH 2017] 大魔法师 题解
- Luogu P7453
- LibreOJ #2980
首先看题:
题目要求我们在 $[ 1,n ]$ 的区间上维护三个值 $A_i,B_i,C_i$,要求支持查询区间和和下面六中操作:
- 区间内 $A_i = A_i + B_i$;
- 区间内 $B_i = B_i + C_i$;
- 区间内 $C_i = C_i + A_i$;
- 区间内 $A_i = A_i + k$($k$ 给定);
- 区间内 $B_i = B_i \times k$($k$ 给定);
- 区间内 $C_i = k$($k$ 给定)。
显然这道题需要使用线段树来维护区间操作。
但是我们不能给每一个操作附上一个懒标记,最后懒标记下放的时候还不得麻烦死。
我们可以尝试一下转化一下我们的操作。
我们可以发现,我们所有的操作不会出现跨位置的操作,也不会出现高于一次的操作(例如 $C_i = C_i \times B_i$ 什么的)
这样我们就可以使用矩阵来维护这三种信息。
如果我们将 $A_i,B_i,C_i$ 三个数值化作一个矩阵的话,那么这个矩阵 $\begin{bmatrix} A_i & B_i & C_i \end{bmatrix}$ 所对应的单位矩阵是这个样子的:$\begin{bmatrix}1&&\\&1&\\&&1\end{bmatrix}$。
而 $\begin{bmatrix} A_i & B_i & C_i \end{bmatrix}$ 想要变成 $\begin{bmatrix} A_i+B_i & B_i & C_i \end{bmatrix}$ 的话可以让它乘以一个 $\begin{bmatrix}1&&\\1&1&\\&&1\end{bmatrix}$。$(2,1)$ 处多出来的那个1就代表着给结果行矩阵的第1个位置加上1个原先的行矩阵矩阵第2个位置的值,也就相当于是给结果的 $A_i$ 加上了一个 $B_i$。
同理,第二个操作乘以的是一个 $\begin{bmatrix}1&&\\&1&\\&1&1\end{bmatrix}$,第三个操作乘以的是一个 $\begin{bmatrix}1&&1\\&1&\\&&1\end{bmatrix}$。
然后就是可恶的第四个操作。我们需要给 $A_i$ 加上一个 $k$,但是我们无法从刚才的方法里面推出来一个类似的方法。
于是我们可以考虑将我们维护的矩阵由 $\begin{bmatrix} A_i & B_i & C_i \end{bmatrix}$ 变为 $\begin{bmatrix} A_i & B_i & C_i & 1 \end{bmatrix}$。
这样我们就只需要乘以一个 $\begin{bmatrix}1&&&\\&1&&\\&&1&\\k&&&1\end{bmatrix}$ 即可。
为了适配我们新的需要维护的矩阵,前面三个就变成了 $\begin{bmatrix}1&&&\\1&1&&\\&&1&\\&&&1\end{bmatrix}$,$\begin{bmatrix}1&&&\\&1&&\\&1&1&\\&&&1\end{bmatrix}$ 和 $\begin{bmatrix}1&&1&\\&1&&\\&&1&\\&&&1\end{bmatrix}$。
第五个操作的思路也很简单,只需要乘以一个 $\begin{bmatrix}1&&&\\&k&&\\&&1&\\&&&1\end{bmatrix}$ 即可。
第六个操作有点难,我们可以先把 $C_i$ 变成0,通过乘以一个 $\begin{bmatrix}1&&&\\&1&&\\&&&\\&&&1\end{bmatrix}$,然后再乘以一个 $\begin{bmatrix}1&&&\\&1&&\\&&1&\\&&k&1\end{bmatrix}$,就可以给 $C_i$ 赋成 $k$ 了。
最终效果跟直接乘以 $\begin{bmatrix}1&&&\\&1&&\\&&&\\&&k&1\end{bmatrix}$ 效果一样。
于是我们的线段树只需要维护一个区间乘和区间求和即可。
矩阵结构体:
1 | struct Matrix |
总代码:
1 |
|