[Codeforces is All You Need] CR 833 ABC (1748ABC) - Solution
这是ABC的合集题解

问题简述
Problem A:给定,计算使用大小为
(每个
各有一个)的方块能拼出的最大的正方形。
Problem B:给定一个长度为的数字串
,求其所有“多样”的子串。一个子串“多样”意味着其中所有的数字出现的次数不超过该子串中不同数字的数目。
Problem C:给定一个长度为的序列
,现在可以将其中的
变成任意整数。求变化后最多有多少个
前缀序列之和为
。
原比赛链接:https://codeforces.com/contest/1748
思路
Problem A:答案就是。首先说明只有边长
的正方形才可行:不难发现
(真的不难发现,就是简单的分类讨论,然后等差数列求和),由此可行的正方形边长不会超过。也不难构造出一个边长为
的解:取一个
的方块;此外大小为
和大小为
的方块拼一起作为一组(
);总共得到恰好
组。证毕。
Problem B:由于一共就只有这10个数字,因此实际上符合要求的子串长度不超过
。直接暴力判断的复杂度为
,略高了。可以使用前缀和优化(统计不同数字出现次数的前缀和,这样可以在
内计算每个数字出现了多少次),这样复杂度为
。
Problem C:(贪心)对于前缀和序列,不难发现,(1)当我们将
调整为任意其它整数时,等价于把
同时增加了某个整数。另一个重要的发现是,(2)如果我们调整了
,如果存在
,那么
的调整对
并没有影响(因为调整是任意的)。于是,对于
,我们只需要贪心地考虑
下标对应的前缀和(其中
是
之后第一个为
的元素的位置;如果
已经是最后一个了,那么
)。根据(1)的结果,这时候最佳的贡献应该是该下标区间内出现最多的前缀和值。使用std::map就可以轻松地统计每个前缀和值出现的次数。总的复杂度为
。如果用hash表会更快一点。另外,不要忘记统计第一个
之前的前缀和中值为
的个数!(因为这个WA了几发。)
后记
因为一些原因,没录上屏 :(
代码会上传到github:https://github.com/cnzzx/AlgorithmCompetitions。
D题把奇数的情形解决了,但是没捣鼓出偶数的情形,看了题解觉得确实差了一点,没从最低的二进制位考虑过。
附上codeforces官方题解链接:https://codeforces.com/blog/entry/108319