Codeforces Round #784 (Div. 4)

\(1669A - Division?\)

输入分数,输出对应分级。
\(if\ else\) 基础题

\(1669B - Triple\)

给一个 \(n\) 个元素的数组 \(a\) ,输出一个至少出现 \(3\) 次的元素,若不存在,输出 \(-1\)
输入过程中,开一个权值数组(麻烦点也能是哈希表),记录每个元素出现过的次数。并维护一个 \(flag\ ok\)
如果 \(ok\) ,记录答案并停止计数。输入结束后判断 \(ok\) 并输出。入门代码实现题。

\(1669C - Odd/Even Increments\)

给一 \(n\) 个正数整形的数组,有两种操作。
\(1.\) 所有 \(odd\) 位元素加 \(1\)\(a_1:=a_1+1,a_3:=a_3+1,a_5:=a_5+1,… .\)
\(2.\) 所有 \(even\) 位元素加 \(1\)\(a_2:=a_2+1,a_4:=a_4+1,a_6:=a_6+1,… .\)
判断在任意次任意种操作后,整个数组元素的 \(parity\) 是否一样。

做题时候想了一段时间,思维不够快,没有积累语言转达的映射,没有转化为直觉。

需要知道一点:

  • 任一个数 \(\pm 1\) 都会改变它的 \(parity\)

容易想到两点:

  • 1.考虑 \(odd\) 位和 \(even\) 位的操作对自身部分的独立影响。若有 \(n - x\) 个和 \(x\) 个元素的 \(parity\) 不一样,操作任意次依旧会是 \(n - x\) 个和 \(x\) 个元素的 \(parity\) 不一样。暂时认为 \(odd\)\(even\) 各自位上的 \(parity\) 必须一样。
  • 2.考虑 \(odd\) 位和 \(even\) 位的操作对其他部分的连带影响。任意两个元素的 \(parity\) 不一样,那么改变其中一个元素的 \(parity\) 就会使得两个元素 \(parity\) 一样。\(odd\) 位和 \(even\) 可以在总体上抽象成两个元素,无论他们 \(parity\) 是否一样,经过任意操作后 \(parity\) 都会一样,所以不需要一起考虑他们,单独考虑即可。

得到结论,两次单独考虑 \(odd\) 位和 \(even\) 位的元素,在一个部分中的所有元素 \(parity\) 必须一样。

如何实现?

如考虑 \(odd\) 位的元素 \(parity\) 是否一样:相邻 \(odd\) 位置判断 \(parity\) 对比返回值。
定义一个 \(flag\) ,判断整个遍历中是否有不合法情况。相邻 \(odd\) 位置的遍历也容易实现,遍历指针 \(i += 2\) 即可。

两个部分固然可以扫两遍,但可以优化到一次遍历:定义两个 \(flag\) ,通过判断小标 \(parity\) 进行不同操作。

\(1669D - Colorful Stamp\)

题意就是有 \(R\)\(B\) 两种颜色和无色 \(W\) ,判断在一个字符串中,判断是否所有的有色子串是否合法,一个有色字串必须 \(R\)\(B\) 都出现过才合法。
思路并不困难,但实现难度属于入门层面中的困难。
\(python\)\(split\) 显然可以通过 \(W\) 把有色串分出来去判断,但不考虑 \(python\)
正解也一定是通过 \(W\) 去作为分割每一个子串,并不一定需要真的分出来。

思路:

  • 1.不考虑分割,先只考虑每一个子串,存在三种情况,只有 \(R\) 、只有 \(B\) 、两者皆有,可以定义一个二进制 \(flag\) 判断字串是否合法,如果该子串不是 \(R\)\(B\) 都有,即不合法。

  • 2.遍历字符串,考虑分割。以 \(W\) 为分隔符或者说结束符,标志着一个子串的完全结束,在 \(W\) 时判断合法性质。之后清空标记,使每个子串在一次遍历中能被独立。

  • 3.需要注意,最后一段可能是有色串而不是 \(W\) 串,这种情况下不能以 \(W\) 标志为最后一段有色串的结束,所以整个字符串遍历完后,需要再判断一次。

遍历过程中若出现不合法情况,在标记清空前 \(break\) ,最后判断输出(显然这题的复杂度不需要 \(break\) ,再开一个标记判断是否“出现过”不合法的情况也行,但离线时 \(break\) 总归是个好习惯)。

\(1669E - 2-Letter Strings\)

简单题,但当时的题意没有快速映射出来,再加上阅读能力,直接没看懂题意。

题意即对于所有出现顺序 \(i < j\) 的长度为 \(2\) 的字符串,将 \(s_i\)\(s_j\) 严格有一个位置字符不同的情况计数。

需要知道两点:

  • 1.对于一个序列中,\(i < j\) 应该敏感。
    对于\(\forall pair(i, j)\)\(i < j\) ,等价于 \(num_{min} \leq i < j \leq num_{max}\)
    描述的是所有元素中,在顺序情况下的任意两个不同元素。
  • 2.要求的是任意,显然得把所有字符串都记录下来。我们可以开一个 \(s[N][2]\) 数组去记录。

容易想到一点:

  • 1.操作上考虑在线操作,固定 \(j\) ,枚举 \(i < j\) ,判断 \(s_i\) 严格有一个位置的字符不同于 \(s_j\) 即合法。

若认为合法,计数加一。判断操作容易实现,即 \(((s[i][0] == s[j][0]) + (s[i][1] == s[j][1])) == 1\)

\(1669F - Eating Candies\)

\(n\) 个糖果排一列,每次从左或右选一个,问保证左右选的糖果贡献相同的情况下,最多可以选择多少个糖果。

实现上有一点点小技巧。

要取“贡献相等时,消耗的最多的糖果数量”,故过程中维护“左右贡献相等时”的消耗糖果数量 \(ans\)

涉及到的贪心思维:让左、右贡献总和相等

则我们只需要贪心地让“贡献总和更小的一侧”往下走一位加上贡献即可。而当左、右贡献总数相等,维护“消耗的糖果数量 \(ans\) ”同时,若还能继续消耗糖果,我们任取左右一处加上一个糖果的贡献。

这通过两个指针即可实现。

比较容易确定一个 \(l\)\(r\) ,分别从左侧和右侧记录贡献总数 \(lval\)\(rval\)

写个循环 \(while(l < r)\) 即可,然后顺便记录一下 \(lval == rval\) 时,\(ans = l + (n - r + 1)\)

注意

值得注意的是,我们希望时刻保证 \(l < r\) 。因为 \(l, r\) 一直在变,所以最后一次循环中会出现 \(l >= r\) 。若不时刻判断则导致,此时在该次循环意义下合法。

也就是说 \(l < r\) 不仅仅在最外层的判断句。

类似于快速排序时也是用两个指针从头尾往中间移动,并时刻判断两个指针不能相等。所以说排序还是需要掌握的,毕竟快排和归并排序中的指针操作都是非常启发式的嘛。

\(1669G - Fall Down\)

这题放在这个位置显然是个开心题,至少对于中国学生来说这种基础直觉(积累)还是有的。

从下往上遍历,对于所有 \(*\) ,写个死循环往下跳,如果在该位置下一行是 \(.\)\(swap\) 两个位置,否则结束循环。
对于 \(a_{i, j}\) ,显然可以 \(for(i,n)\) ,或者 \(while(ture)\)\(j = j + 1\)

\(1669H - Maximal AND\)

贪心题,需要积累一些位运算的直觉和贪心的技巧。

有个重要的直觉:就是 \(n\) \(or\ 2^{j}\) ,就是 \(n\) \(or\)\(1 << j\) 。也就是取 \(n\) 的二进制的第 \(j + 1\) 位变成 \(1\)

题意为可以任选一个 \(a_{i}\) 让它二进制的某一位变成 \(1\) ,这种操作共可以执行 \(k\) 次。最后需要使得 \(a_{1}, a_{2}, ..., a_{n}\) 全部 \(AND\) 起来最大。我们知道 \(0\ AND\) 任何一个数都为 \(0\)

比较容易地想到贪心,尽可能把 \(k\) 次操作贡献在更高的位置上即可。
且要保证 \(a_{1}, a_{2}, ..., a_{n}\) 的二进制在该位置都能变为 \(1\) ,否则的话耗费掉一些操作以后也是没有贡献的。

可以从高到低枚举二进制位,再枚举所有 \(a_{i}\) ,记录下所有二进制位上需要的操作次数,这里记作 \(c[i]\)

获取判断一个数的二进制第 \(i\) 位需要使用 \(x >> i\ \&\ 1\)

最后看一下所有二进制位需要的操作次数,贪心一下。
但是这里贪心也比较技巧。

关键是:
对于这种二进制答案,我们并不试图修改真正的答案再全部 \(AND\) 起来。
位运算的结果对最终答案的贡献是非 \(0\)\(1\) 的,所以我们不考虑过程,只需要考虑最终答案的每个位置是否会被贡献到。
定义一个 \(ll\ ans = 0\) ,逐位考虑是 \(0\) 还是 \(1\) ,是的话 \(OR\)\(1\)

在枚举的时候如果 \(k \geq c[j]\) ,那么就让 \(ans\ |= 1 << j\)\(k -= c[j]\)
只有当 \(a_{1}, a_{2}, ..., a_{n}\)\(j\) 位上都变为 \(1\) 的操作数次未超过剩余操作数次,才执行这些操作。
不好想的地方在于当 \(c[j] == 0\) ,不需要经过任何操作,也会有 \(ans |= 1 << j\)

posted @ 2022-09-04 17:22  03Goose  阅读(45)  评论(0)    收藏  举报