CF EDU 137 总结

\[\large\text{Educationnal Codeforces Round 137} \]

E

有一个比较显然的 \(\mathcal{O}(h\times t_1\times t_2)\) 做法,即你定义一个状态表示当前敌方飞船的血量,飞船 \(1/2\) 分别的充能时间。

额这个状态及其的冗余啊。而且看了样例我才知道这个充能是可以两个飞船同时充能的。

定义 \(dp_i\) 表示进行完上次攻击之后,敌方飞船剩下的血量为 \(i\) 所需要的最少时间。

先看只需要蓄力一个的暴力转移,即:

\[\begin{aligned} dp_{i-(p_1-s)}=\min(dp_i+t_1)\\ dp_{i-(p_2-s)}=\min(dp_i+t_2)\\ \end{aligned} \]

考虑怎么对于同时蓄力的进行转移。观察到你可以把两个同时打出,看作打出一个的同时另外一个正好蓄好了力,正好可以打出去。

故你考虑枚举 \(p_i\) 打出去了 \(j\) 次,且第 \(j\)\(p_{3-i}\) 会同时打出,然后算出 \(p_{3-i}\) 在这段时间内会有单独打出去多少次,毕竟不能干等着对吧。

首先显然要满足 \(t_i \times j \ge t_{3-i}\) 不然不会同时打出一次。

然后你看在这期间 \(p_{3-i}\) 会被打出去多少次。稍微算一下应该比较容易,懒得打 \(\LaTeX\) 了。

时间复杂度 \(\mathcal{O}(h^2)\)

MD,读错题了,浪费了我一个小时。

\(\text{My Submission.}\)

F

首先你肯定是想到统计对于一个权值有多少种方案会出现在最终集合里面,然后加起来就可以了。

首先有一个 \(\mathcal{O}(n^2)\) 的算法是,你考虑枚举权值 \(x\in [1,3\times 10^5]\),然后定义 \(dp_{i,0/1}\) 表示进行完前面 \(i\) 次操作,他是否在集合里面的方案数,最终答案就是对于每个权值所求得的 \(dp_{n,1}\) 之和。

稍微写一下这个柿子:

\[\begin{aligned} &l_i\le x \le r_i\\ &dp_{i,0}=dp_{i-1,0}+dp_{i-1,1}\\ &dp_{i,1}=dp_{i-1,0}\times 2+dp_{i-1,1}\times 2\\ &\text{Other Wise}\\ &dp_{i,0}=dp_{i-1,0}\times 3+dp_{i-1,1}\\ &dp_{i,1}=dp_{i-1,1}\times 2\\ \end{aligned} \]

观察到上述转移非常像矩阵的形式:

\[\begin{aligned} &l_i\le x\le r_i\\ &\begin{pmatrix} dp_{i,0}& dp_{i,1}\\ \end{pmatrix}= \begin{pmatrix} dp_{i-1,0}& dp_{i-1,1}\\ \end{pmatrix}\times \begin{pmatrix} 1&2\\ 1&2\\ \end{pmatrix} \\ &\text{Otherwise}\\ &\begin{pmatrix} dp_{i,0}& dp_{i,1}\\ \end{pmatrix}= \begin{pmatrix} dp_{i-1,0}& dp_{i-1,1}\\ \end{pmatrix}\times \begin{pmatrix} 3&0\\ 1&2\\ \end{pmatrix} \end{aligned} \]

你考虑对于每个 \(i\)\(1\to n\) 枚举,对于所有的 \(x\) 同时执行以上过程,即开一颗线段树,每个叶子节点储存一下 \(dp_{x,i,0},dp_{x,i,1}\) 他们两个构成的矩阵,然后每次修改就是区间 \([1,l_i-1],[l_i,r_i],[r_i+1,3\times 10^5]\) 分别乘上对应的转移矩阵即可。

时间复杂度 \(\mathcal{O}(V\log n)\),但是因为有矩阵的常数,可能很容易被卡常。

经过自己的实现,确实需要主意矩阵乘法的时候尽量用 \(\text{*=}\) 不要直接用 \(\text{*}\) 因为后者会有很多的结构体赋值以及额外的空间开销导致常数爆炸。

貌似题解区没有这么做的(?

\(\text{My Submission}\)

G

posted @ 2024-10-08 08:15  Saltyfish6  阅读(19)  评论(0)    收藏  举报
Document