Codeforces Round 893 (Div. 2)


Round 3 : Codeforces Round 893 (Div. 2)(VP)

一言:
从你站在桥上看我的那一刻起你就是我的世界
——火影忍者

不是很满意,还是没有突破 D 题,确实是没有想到这题竟然如此毒瘤。。

D: Trees and Segments

首先不难想到一种思路,就是枚举 l0,然后预处理出在得到 l0 时,能够得到最大的 l1 是多少,假设这个值为 dl0

显而易见的,0 的连续段不是在 1 连续段的右边就是在他的左边,所以考虑维护四个数组来辅助得到 dl0

定义 l1i,j 表示以 i 结尾,得到长度为 j 的最大 0 串需要的最少操作数。

l2i,j 表示以 i 开头,得到长度为 j 的最大 0 串需要的最少操作数。

显然,对于 1 串,为了方便求出 d 数组,我们就需要换一种定义方式:

定义 r1i,j 表示使用 j 次操作,得到的以 i 结尾的最大连续 1 串的长度。

r2i,j 表示使用 j 次操作,得到的以 i 开头的最大连续 1 串的长度。

显然对于上述数组,我们可以通过枚举任意一个子区间 [l,r],获取其变为 0 串,或者 1 串的代价,然后带回上述的几个数组中来求解。

所以有 dj=max r1i1,kl2i,j,r2i+1,kl1i,j

但是还有一个问题,这样求出的 di 两个连续 01 串根据定义是必须靠在一起的,实际上却可以是不连续的,所有我们要对 r1 求一个前缀 maxr2 求一个后缀 max 再套入刚刚 dj 的公式。

另外,也要处理好一些边界值的细节。以及不能 memset 真的好烦啊!

Submission

F: Rollbacks (Hard Version)

看完题解之后,感觉这个题是真的妙啊。

由于这道题是 E 的加强版,所以就直接忽略这道 E 了。

首先,为了让题目更加简单,我们可以直接不考虑这个删除操作。

那么显然由于是要求不同的数字,所以实际上只有每个数出现的第一个位置是有意义的,那么我们可以考虑维护一个 set 来储存每个数出现的位置。然后还有单点修改,所以可以维护一个树状数组,来把有意义的点储存进去。

具体来说,对于插入操作,将这个数放入 set,然后并根据 set 来单点修改树状数组。对于查询操作,假设当前有 len 个数,那么直接在树状数组中查询 [l,len] 的有效值总和。

重点是这个删除操作,实际上我们可以直接令 len=lenk,仔细想可以发现,如果我们想要撤销到这个删除,那么必然在撤销这个删除的上一个状态就是这个 len=lenk 这个状态,所以到时候直接在撤销的时候把 len 加回来即可。

至于插入操作的撤销,这个还是很简单的,就不细说了。

实际上在代码实现的时候,是还可以更简单的。

Submission

What I learned:

  • 当求两个独立的区间的贡献时,可以考虑枚举两个区间的相对方位,然后通过一些预处理进行维护。

  • 如果既有删除操作,有些时侯又要撤销这个删除操作,那么可以考虑在删除的时候只将数组的最后一位向前挪,并不改变实际的值。

  • 维护一个序列有多少个不同的数时,可以只将每个数第一次出现的位置设为贡献 1,其余位置都不存在贡献。

posted @   Saltyfish6  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
Document
点击右上角即可分享
微信分享提示