CF2033D Kousuke's Assignment

Posted on 2025-04-18 23:14  K_J_M  阅读(16)  评论(0)    收藏  举报

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