Kousuke's Assignment
题目描述
给出一个长度为 \(n\) 的数列 \(a_i\),要求计算数组中不重叠的子段数量,使得每个子段是美丽的。
一个子段 \([l,r]\) 被认为是美丽的,当且仅当 \(a_l+a_{l+1}+\dots+a_r=0\)。
你的任务是计算最多有多少个不重叠的美丽子段。
Solution
简单优化 dp。设 \(pre_i\) 为 \(a_i\) 的前缀和数组,\(dp_i\) 表示前 \(i\) 个最多的不重叠的美丽子段。那么转移为
\[dp_i=\max \begin{cases} \max(dp_{i-1},[pre_i=0])\\ dp_j+1& pre_i-pre_j=0 \end{cases}
\]
时间复杂度为 \(\mathcal O(n^2)\),考虑优化。发现条件 \(pre_i-pre_j=0\) 可以转化为 \(pre_i=pre_j\),然后又发现 \(dp_i\) 数组是单调递增的,所以我们可以从最近的一个满足条件的 \(j\) 转移过来。记 \(last_i\) 表示上一个前缀和是 \(i\) 的位置,那么转移可以写为 \(dp_i=\max(dp_i,dp_{last_{pre_i}}+1)\),这是 \(\mathcal O(1)\) 转移,值得注意的是,我们转移时需要考虑 \(last\) 有没有值。时间复杂度 \(\mathcal O(n\log n)\)。
Ac Code