CF2043C 题解

CF2043C 题解

题意

给定一个除了 1,1 之外,最多存在一个 xx[109,109] 的数的序列,求其子段和的所有可能值,从小到大输出。

分析

很容易就去思考如何从这个特殊的 x 入手。于是先排除这个特例,考虑全都是 1,1 的情形,那么顺序从左到右不断加入 ai ,可以发现可以通过维护当前值域的上下界来解决问题。最后我们对于 x 之前的数统计一遍, x 之后的数倒序统计一遍,然后通过 x 把两边合并起来就好了。

赛时就是这么想的,思路也大体正确了。

但是存在的一个问题是,值域中的某些数,可能并不能和当前这个 ai 拼接到一起,因为它可能不是以 ai1 结尾的。比赛的时候是这么写的,很麻烦,最后也没有调出来。

值域统计

不妨换一个角度思考,一个 [l,r] 的子段和可以表示为 sumrsuml1,由于 x 比较特殊,我们还是像上文提到的那样对于 x 的两边分别统计,最后单独考虑 x

这样对于一个固定的 i 来说,sumisumj 的取值一定是在整数意义下连续的。因为任意的 sumisumi1 相比,绝对值只会相差 1 ,这就是 1,1 的带来的特殊性。(这段比较抽象,建议画一个 si 的散点图来理解)

所以只需要考虑前缀和的前缀 maxmin 就可以了,对于一个 si[sipmax,sipmin] 之间的所有整数一定都是可以取到的,这样我们就成功计算出了以 ai 为结尾的子段值域。

注意,这仅仅是以 ai 为结尾的值域情况,我们不断维护它,是为了到最后能和 x 拼接起来,但是如果直接把它当成答案,肯定会有所遗漏,因为答案子段的结尾并不仅仅只是一个固定的元素,因此,对于所有算出来的值域,我们要取并集。

至于这个取并集过程的实现,观察到相邻两个元素的值域相差不会太大,我们只需要把每次更新值域后 被遗漏的部分提前标记为 true 就可以了。当然,在差分数组上操作,最后前缀和一遍的 trick 也是可以的。

以上是对于 x 左侧的计算方法,对于 x 的右侧来说,倒序枚举如法炮制即可。

x 两侧的值域进行合并

x 对应的下标为 pos

假设左边以 apos1 为结尾的值域是 [l,r],右边以 apos+1 为结尾的值域是 [L,R]

很明显的是,最后能够取到的就是 [x,x][l+x,r+x][L+x,R+x][l+L+x,r+R+x],把这一部分并进答案即可。

我个人的实现方法过于抽象,不过最后还是过了就行。

记得要单独把 0 也标记为 true。

Code

posted @   Hanggoash  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!
动态线条
动态线条end
点击右上角即可分享
微信分享提示