2022.7.30 做题记录
Luogu5122 Fine Dining G Present 7.0
不难想到先从 \(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
SP10707 COT2 Count on a Tree II Present 7.0
首先这个问题我之前去 uoj 群问过,群友告诉我本题不存在 \(\text{polylog}\) 解法。乖乖莫队吧=_=
主要是学习了一下树上路径转链上问题的技巧
考虑把一棵树的括号序写下来,例如这棵树
它的括号序就是 \(\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\),那么一个点的前缀对应的就是这个点到根的路径。
每个点出现了两次,我们应该按哪一次出现算呢
其实无所谓,因为两次出现之间隔的肯定会消掉。只是一个区间开闭的问题
那么两点之间的路径可以转化为一个区间。
具体来说,分两种情况讨论
- 两点互为祖孙关系,不妨设 \(u\) 为 \(v\) 的祖先,那么区间为 \([L_u,L_v]\)。其中 \(L_i,R_i\) 分别为 \(i\) 第一次与第二次出现的位置。
- 否则,显然 \([L_u,R_u],[L_v,R_v]\) 不交,不妨设 \(L_u<R_u<L_v<R_v\),则区间为 \([R_u,L_v]\cup\{\text{LCA(u,v)}\}\)。
然后我们跑莫队的时候给每个点维护一个 \(\texttt{used[]}\) 表示当前这个点算了几次,每次 \(\text{used[}x]=1-\text{used}[x]\) 即可
于是这题就做完了,复杂度 \(O(n\sqrt{m})\)。注意这题颜色值域挺大,要离散化。AC Code
QBXTOJ3430 能源供应 Present 8.0
去年的题我现在才会orz
可以发现每一天如果开火电站那么最优方案是确定的,根据 \(k\) 和 \(v_i\) 的大小关系可以直接求出来。
不开火电站其实也是一样的。那么我们可以求出 \(x_i,y_i\) 表示每天开/不开火电站的最小花费,设一个 \(f(i,0/1)\) 表示只考虑前 \(i\) 天,最后一天开/不开火电站的最小花费。
这样就有转移方程:
然而带修改,考虑 DDP,写出矩阵:
其中这里矩阵乘法定义为
不难发现具有结合律,我们相当于要单点修改&全局求乘积,用线段树维护即可,复杂度 \(O(n+q\log n)\)。
单点修改&全局求乘积不能直接除掉吗?矩阵不一定存在逆啊,,