为什么会有傻子每次计算都初始化线段树一次 …… st = SegmentTree(n)
改成 st.mdf(1, n + 1, -1)
就 += 25pts 了……
T1
大力分讨题。
首先容易观察到,当 且 都不含 的时候, 不含 。此时的 当且仅当 或 ,否则 。
因为 一定满足条件,所以我们断定 中 的个数 ;又在下面的情况中, 和 的长度可能不同,所以 必然包含 。因此下面两种情况的 恰好包含一个 。
观察发现 等于 去掉 后长度较小值 ,且形式必然能写成 , 是把 的一个前缀和 的前缀匹配, 是把 的一个后缀和 的后缀匹配。注意匹配的前缀和后缀显然在 中都不能带 。
预处理 ,分别表示 和 匹配,会产生多少个括号。如果涉及 就标记 。
然后大体的思路就是求出 各自最左侧、最右侧的 位置,枚举 前缀 个字符与 的前缀匹配了,根据 的位置可以算出 与 匹配的后缀会有多少个字符。可以用 算出一个方案所需的 个数,在所有方案中找 个数最小的输出。但是细节极多。
-
记 ,若 中 的前面有 ,要交换位置。
-
记得处理 没有前缀与 匹配的情况。
-
为了使 尽量靠前,若 的 个前缀与 的前缀匹配加上对应后缀的 个数,得出的 个数相等,应当取较小的那一个。
T2
类似上一场的 trick,筛法求质数。对于每个质数求最长的段,使得段内 的个数 。原始的想法是枚举两个 的位置 ,若 就可行。然后在可行的基础上先尽量往左拓展,再尽量往右拓展。
注意到如果 这个 与 这些位置的 都可行,必然取距离 最远的 是最小的。考虑枚举 为右侧 的位置,找到距离 最远的合法 的位置。
转化一下合法的要求,得到 。用一个线段树支持单点加和区间查询最小值,维护 即可。用 BIT 也可以。
T3
性质:存在分界点,右边选的 递减,且只有右边的 贡献答案。
于是把所有 pair 按 从大到小排序。
一个粗略的想法是 表示前 个 pair 任意分到左边右边,使得左边的 的右边 减去对应的 最大是多少。转移通过枚举 是去左边还是右边。但是发现枚举 去左边的时候,会使得原本右边每个数的贡献都发生变化,不好处理。
想一想,这个分界点是很重要的。它决定了右边开始算贡献时的初始 。因此 70pts 的想法就是枚举这个分界点的 ,然后按上面的想法 DP,但算右侧贡献的时候默认分界点的 。然后统计答案时只统计 。
100pts:假设当前循环到第 个 pair,可以把所有数分成三个部分,已经决策了放在左边的、还没决策但未来会在左边的、已经决策了放在右边的、还没决策但未来会放在右边的。把这四类记作 类。
要使得决策一个点去右边的时候,我们能知道这个点的 会产生多少贡献,我们必须知道此时这个点上一个的 是多少。因此 表示决策了前 个 pair, 减去 类的 和 等于 的最大贡献。
注意这里我们把 类也考虑了,也就是把未来可能会放在左边的数也考虑了。
然后是转移。暂且不考虑 减到 的特殊情况。
若 放在右边,。这很好理解。
若 放在左边,。因为当 决策放在左边,在 的视角, 实际是属于 类的, 已经累加进 的 里面了。
这么 DP 就能做了。但是有几个细节。
如何处理 ?因为当 时,它的前置状态是不确定的。单独用一重循环枚举当然可以,但是这里有个更方便的方法:改状态定义。把状态定义改成 表示前 个, 类的 和等于 的最大贡献。那么此时 面对的 就是 ,是容易求的。
这样不会多统计答案吗?实际会有不合法(也就是不满足左边不贡献,右边全贡献的方案)出现,但是这些方案都比实际的最优更劣,因此不会被统计。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性