ABC-283解题报告
C. Cash Register
题意:给你一个数字串(没有前导零),每次可以敲一个 的数字以输入,或敲一次
00
键以输入两个 。问输入这个数字串的最少步骤。
显然遇到两个 合并即可。
By SSRS
1 |
|
D. Scope
题意:有一个合法的括号-小写字母字符串,你需要维护一个集合,任意时刻出现相同元素则不合法。维护过程为:依此扫过每个字符,如果为左括号则不管;为字母则加入集合;为右括号则将它到匹配的左括号之间的字母从集合中删除。
按照题意用栈模拟即可。栈中每个元素代表一层的字母集合,加入左括号则入栈一个空集,加入字母则在栈顶集合插入并检查,加入右括号删除标记并弹栈。
By SSRS
1 |
|
E. Don’t Isolate Elements
题意:有一个 01 矩阵,每次可以取反一行,问最少多少次操作能使该矩阵没有孤点,或判断无解。
显然可以 DP: 表示当前考虑了前 行,第 行取反状态为 ,第 行状态为 ,且前 行已经合法(因为后面行无法影响前 行)的最小操作次数。转移考虑下一行是否能取反即可。
By SSRS
1 |
|
还可以预处理行之间的转移情况,优化成 转移,但是预处理为 ,时间复杂度不变。
By CQ0x3F
1 | const int _ = 1e3 + 10; |
F. Permutation Distance
题意:给你一个排列 ,对每个位置 求
显然可以正反扫两遍(或直接反转数组)分别处理 和 的情况。这里只考虑 。
在 时,有 和 两种情况,对于前者,贡献为 ,显然要让 尽可能大;对于后者,贡献为 ,显然要让 尽可能小。于是,维护两个线段树/树状数组,区间下标为 ,值分别为 和 ,分别维护区间最大值和区间最小值即可。
By SSRS
1 |
|
除了可以分别处理这些情况外,还可以在一个线段树内维护着四个信息,简化代码。
By kotatsugame
1 |
|
如果是分类讨论处理,还可以用 for 循环两次,在循环的开头/结尾处反转信息。
By IH19980412
1 | void solve(){ |
这道题还有一个非常“暴力”的做法,即对于每个位置,从近到远枚举选的元素,如果当前下标的差已经超过了当前的最优解则 break 掉(最优性剪枝)。不是很会证复杂度,可以手玩几组数据感性理解。
By lvkaiyi0811
1 |
|