不难想到先从 \(n\) 跑一遍最短路得到每个点 \(i\to n\) 的最短路长度 \(\text{dist}_i\),然后新建一个点 \(S\),对每个有干草的点 \(u\) 我们连边 \(S\to u\),边权为 \(\text{dist}_u-\text{val}_u\),其中 \(\text{val}\) 表示美味程度。
从 \(S\) 开始跑一遍最短路,对于一个点 \(i\),若 \(i\to S\) 的最短路不比 \(i\to n\) 的最短路长,那么说明 \(i\) 可以前往某个干草堆。
很多题解到这里就说可以从 \(S\) 点和 \(n\) 点分别开始跑 \(\text{Dijkstra}\),然而 \(\text{dist}_u-\text{val}_u\) 有可能是个负数所以正确性并不是那么显然......关于 SPFA,它死了
其实这里 dij 的正确性是可以证明的......由于从 \(S\) 到某个点 \(u\) 必然经过 \(S\) 的某条出边且只经过一次,我们可以直接给这些出边都加上一个足够大的值 \(A\),那么可以证明此时最短路增大的值也是 \(A\),并且图中的边都是正权。
于是可以发现 dij 确实是正确的。那么就做完了,复杂度 \(O(m\log m)\)。AC Code
首先这个问题我之前去 uoj 群问过,群友告诉我本题不存在 \(\text{polylog}\) 解法。乖乖莫队吧=_=
主要是学习了一下树上路径转链上问题的技巧
考虑把一棵树的括号序写下来,例如这棵树
图源 https://www.cnblogs.com/wifimonster/p/10227091.html
它的括号序就是 \(\text{(1 2 5 8 8 9 10 10 11 11 12 12 9 5 6 6 2 3 3 4 7 7 4 1)}\)。
为什么叫括号序呢,因为如果我们把每个数两次出现看做左括号和右括号,那么每个括号对应的就是自己的子树。
例如上面就是 \(\texttt{(1(2(5(8 8)(9(10 10)(11 11)(12 12)9)5)(6 6)2)(3 3)(4(7 7)4)1)}\)。
如果把一个点第一次出现看做 \(+1\),第二次出现看做 \(-1\),那么一个点的前缀对应的就是这个点到根的路径。
每个点出现了两次,我们应该按哪一次出现算呢
其实无所谓,因为两次出现之间隔的肯定会消掉。只是一个区间开闭的问题
那么两点之间的路径可以转化为一个区间。
具体来说,分两种情况讨论
然后我们跑莫队的时候给每个点维护一个 \(\texttt{used[]}\) 表示当前这个点算了几次,每次 \(\text{used[}x]=1-\text{used}[x]\) 即可
于是这题就做完了,复杂度 \(O(n\sqrt{m})\)。注意这题颜色值域挺大,要离散化。AC Code
去年的题我现在才会orz
可以发现每一天如果开火电站那么最优方案是确定的,根据 \(k\) 和 \(v_i\) 的大小关系可以直接求出来。
不开火电站其实也是一样的。那么我们可以求出 \(x_i,y_i\) 表示每天开/不开火电站的最小花费,设一个 \(f(i,0/1)\) 表示只考虑前 \(i\) 天,最后一天开/不开火电站的最小花费。
这样就有转移方程:
\[f(i,0)=\min\{f(i-1,0)+y_i,f(i-1,1)+y_i\}\\ f(i,1)=\min\{f(i-1,0)+x_i+C,f(i-1,1)+x_i\} \]然而带修改,考虑 DDP,写出矩阵:
\[\begin{bmatrix}f_{i,0}\\f_{i,1}\end{bmatrix}=\begin{bmatrix}f_{i-1,0}\\f_{i-1,1}\end{bmatrix}\cdot\begin{bmatrix}y_i&y_i\\x_i+C&x_i\end{bmatrix} \]其中这里矩阵乘法定义为
\[(A\times B)_{ij}=\min_{1\le k\le n}A_{{ik}}+B_{kj} \]不难发现具有结合律,我们相当于要单点修改&全局求乘积,用线段树维护即可,复杂度 \(O(n+q\log n)\)。
单点修改&全局求乘积不能直接除掉吗?矩阵不一定存在逆啊,,
AC Code