NIT GREAT NITYACKE DESTROYS THE UNIVERSE

发布时间 2023-11-02 15:26:42作者: British_Union

线段树

一般线段树维护的东西是什么?设其维护的信息的半群 \((A,+)\),维护标记的半群 \((T,\times)\) 和一种运算 \(*\mapsto A*T\to A\)

要求 \((b+c)*a=b*a+c*a\)

一般而言,矩阵是满足这东西的最一般东西,所以线段树一定可以用矩阵搞。

注意:这里不包括 Segment Tree Beats 等基于势能分析的非传统线段树。

现在我们看题:[NOIP2022] 比赛。

扫描线,然后单调栈转化成支持 \(a·b\) 历史和、\(a,b\) 区间覆盖的数据结构。

想在 \(O(1)\) 秒钟构造出标记感觉不大现实,考虑用矩阵乘法维护标记,记 \(a,b,S,len\) 为区间 \(a/b\) 和,历史版本和,区间长度,则区间 \(a\) 加上 \(v\) 就是

\[\begin{bmatrix}a+vlen&b&ab+bv&S&len\end{bmatrix}=\begin{bmatrix}a&b&ab&S&len\end{bmatrix}\times \begin{bmatrix} 1&0&0&0&0\\0&1&v&0&0\\0&0&1&0&0\\0&0&0&1&0\\v&0&0&0&1\\\end{bmatrix} \]

区间 \(b\) 加就是:

\[\begin{bmatrix}a&b+vlen&ab+av&S&len\end{bmatrix}=\begin{bmatrix}a&b&ab&S&len\end{bmatrix}\times \begin{bmatrix} 1&0&v&0&0\\0&1&0&0&0\\0&0&1&0&0\\0&0&0&1&0\\0&v&0&0&1\\\end{bmatrix} \]

叠加上版本和就是:

\[\begin{bmatrix}a&b&ab&S+ab&len\end{bmatrix}=\begin{bmatrix}a&b&ab&S&len\end{bmatrix}\times \begin{bmatrix} 1&0&0&0&0\\0&1&0&0&0\\0&0&1&1&0\\0&0&0&1&0\\0&0&0&0&1\\\end{bmatrix} \]

然后线段树维护矩阵即可,时间复杂度 \(O((n+m)k^3\log n),k=5\),由于常数过大,可以获得 \(20pts\) 的高分。

然后我们发现,矩阵有很多地方用不上,可以直接拆开。

贡献是形如 \(len\to a,b\to ab\to S\) 的 DAG,最多有 \(9\) 个状态,然后我们只维护这 \(9\) 个数即可。

然后发现这些位置分别是 \((4,0),(4,1),(4,2),(4,3),(0,2),(0,3),(1,2),(1,3),(2,3)\)

然后把这一部分重新标号,拿出来手动维护就行了。

代码没写

联考题

image

代码待补