CF1858 D,E题解
D:
比赛临死时交了个假做法MLE了,很气,赛后发现WA了所以安心了。
题意: 给你一个 串,你可以最多修改 个位置,修改完后最长的 串和最长的 串记为 和 ,对于 从 到 的所有取值,输出 最大值。(n方)
又是 的形式,曾经牛客多校也是有一道李超线段树写成了排序的假做法,WA完这道题才发现。
这题可以 ,因此无需李超线段树,可以枚举 来求最大值,那么发现 最大是 ,对于每个 用 数组存最大的 即可。
我的假做法的预处理和正解一样,处理 表示前 个位置换 个 最长的 串, 表示前 个位置换 个 最长的 串, 和 同理,是后缀最大值。其实这样预处理完, 数组扫一遍就能求出来,我却傻乎乎去拿 排序。
还有一个和题解不太一样的地方,题解只算了 和 ,不用算 ,因为 直接枚举区间就好了,枚举 的区间,就能知道这个区间需要改 个位置,然后前缀和后缀改 个位置最大的 去更新 数组即可。
E:
参考了SpaceJellyfish佬在群里讨论的 做法,代码短且快,理解起来需要多考虑一些情况。
题意: 四个操作,1:数列末尾加一个数。2:数列末尾删除k个数。3:撤销上一个1或2操作。(没有撤销3操作这种duliu挺好)。4:询问数列中不同数字个数。
经典的求不同数字个数,如果题目中左端点固定,或者可以 枚举左端点,那我们一般用 数组记录每个数字第一次出现的位置。
在此题中,我们设 数组表示当前数列, 数组取值 表示 位置是否是第一次出现的位置,那么 数组的前缀和 就是要输出的答案哩。我们不用主席树而是只用一个线性的结构来记录答案,那么对于各个版本,如果修改的内容不多,我们可以记录修改的内容然后在撤销时返回即可。
观察此题的撤销操作和删除操作,我们发现操作形成的痕迹是一颗平躺着的树,从左往右长。删除是回到树上某个祖先,撤回删除操作即回到叶子处,这个祖先到叶子的路径其实都是我们当前线性结构储存的信息,我们只需要知道当前的位置 ,这个到祖先或到叶子其实只是改变 的位置, 数组不变, 一直是答案。添加操作则是生成一个新的枝条,因为我们用的是一个线性的储存结构,这个操作会覆盖掉树上之前的一些信息,当我们撤销添加操作时,覆盖掉的信息更新回来即可。
现在要解决的两个问题:怎么更新添加一个数的信息,覆盖了哪些原来的信息。
添加一个数,只需要考虑这个数 是不是第一次出现, 为 当然是第一次出现,但 有值时,虽然记录了 第一次出现的位置,但是由于 可能是之前版本的 ,在删除操作之后, 的位置指向了当前位置的后面,或者 位置在当前位置前面,但是那个位置已经被新版本给改成其他数字了,这种情况下 其实都是第一次出现。
覆盖了哪些信息呢?新位置 需要存当前的答案 ,那么之前的 被覆盖了,从 更新过程来看, 数组也是需要存的,同样被覆盖了,然后还有一个 也被修改了,如果我们撤销这个 的添加, 之前应该是另外一个位置。
用栈存操作时顺便记录下这个操作覆盖的这三个原有信息,更新回来即可。
__EOF__

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具