【题解】CF1423G Growing Flowers 题解
题意
给定一个序列,每个位置 存在一种颜色 ,要求支持下列两种操作:
- 给定子段 和颜色 ,将该子段所有位置的颜色全部变为 ;
- 给定 ,求所有长度为 的子段内不同颜色的数量的和。
:,,。
题解
我们发现修改操作只有一种:子段颜色覆盖。那么我们可以考虑用 维护颜色段,根据颜色段均摊,这样的时间复杂度是可以接受的。
那么现在的问题是:求出一个颜色段对答案的贡献。
乍一看,我们似乎要维护每个位置对每一种 的贡献,时间复杂度似乎不太可以接受。
但实际上我们通过分析,可以发现贡献要么呈一段相等的数的形式,要么呈一段等差数列的形式,并且我们仅需支持单点查询,所以我们可以把贡献差分,那么询问时就仅需求前缀和即可。
接下来就是具体分析的环节。
我们钦定在段中,每种颜色第一次出现的位置才会造成实质性的贡献。
那么对于第一个位置 ,我们考虑计算它对 的贡献:
在包含 的所有长度为 的子段中,右端点最右会延伸到 ,因为极限情况就是左端点为 的情况,但是右端点又不能超过 。
假设我们现在已经维护好了 的颜色在 之前的最后一次出现的位置 (没有则记为 ),那么在包含 的所有长度为 的子段中,右端点最左会延伸到 ,因为极限情况就是右端点为 的情况,但是左端点又必须在 右侧(否则 的颜色的实质性贡献就不会由 提供)。
(注意 可以在维护颜色段的同时维护。)
综上, 的贡献即为 。注意 的范围为 ,否则 会有负贡献,这是不存在的。
把贡献拆开,可以发现 和 的部分由于 递增,所以贡献是呈一段等差数列和一段相等数列的形式的,差分后可以很方便地用线段树维护。
那么我们还需要对颜色段中 以后的位置做同样的分析吗?当然不需要。
我们发现,颜色段中 以后的位置 的贡献十分简单,因为包含它的子段的左端点必须在 这个位置上,所以它对所有 的贡献均为 。
稍作分析,可以发现颜色段中 以后的位置对 的总贡献为 (其中 表示颜色段长度)。由于 递增,因此这个部分的贡献仍然呈一段等差数列和一段相等数列的形式,可以继续差分后用线段树维护。
于是这题就做完了,不过写起来细节还挺多。
(由于笔者 操作的常数过大,所以笔者做了一个数据分治,对于询问次数 较小的数据采用了常数较小的、复杂度为 的做法。)