CFR-844(Div.1+2)解题报告
A. Parallel Projection
题意:有一个 的长方体,顶面和底面有两个点,只能走直线且不能穿过长方体,求最短距离。
显然曼哈顿距离必须要走。多出来绕弯的距离一定是选一个点,到边缘的最短距离 。
By cxm1024
1 |
|
B. Going to the Cinema
题意:有 个人,每人有一个要求 ,表示他愿意去电影院当且仅当其他人中有至少 个去。问全部满足要求的方案数。
首先对 从小到大排序,枚举总共去几个人。假设去 个人,则一定是 最小的 个人去。考虑第 个人是否愿意去,以及第 个人是否愿意不去即可。
By IceYukino
1 | int T,n,a[N]; |
C. Equal Frequencies
给你一个小写字母字符串,求更改字母的方案,使得让所有出现过的字母的出现次数都相同,且次数尽可能少。
可以枚举需要总共出现几个字母,进而得到每个字母的出现次数 。对于每个次数超过 的字母需要砍掉多余的改成其他字母;对于次数不超过 的字母,需要将一些填成 ,一些砍掉。显然让出现尽可能多的字母填成 最优。
By cxm1024
1 |
|
D. Many Perfect Squares
题意:有一个不重复的正整数数组 ,你需要找到一个 ,使得每个元素加上 后出现尽可能多的完全平方数。
显然答案至少为 。如果答案超过 ,可以枚举钦定两个变成完全平方数的数 ,则有 ,得出 ,即 。对 枚举因数,求得 ,进而得到 ,即可算出此时的完全平方数个数。
By IceYukino
1 | int T,n,a[N]; |
有一个优化的技巧,当找到一个确定的 时,不立刻计算数量更新答案,而是存起来,到最后去重后再计算。由于同一个 可能会被多对不同的元素、因数找到,所以优化非常显著。
By noimi
1 | int main() { |
枚举因数的过程同样可以通过分解质因数,用 DFS 合并来实现。首先存下每个质因数以及次数,DFS 合并时依此搜索每个质因数,枚举该质因数选几次,进入下一个质因数搜索。由于一个质因数的次数不同,因数就不同,所以一定不重不漏。
By 18Michael
1 | inline void init() |
E. Rectangle Shrinking
题意:在一个 的网格中,放置了 个矩形。对于每个矩形,你可以删掉也可以用一个子矩形代替。要求最后不能有矩形重叠,且面积尽可能大。
做法一
一个简单的猜测为,最终面积即为面积并,考虑如何构造。我们采用在线添加的方式,每次添加一个新矩形时保持矩面积为矩形面积并且不重叠。矩形用三个 set 动态维护,分别表示跨两行、只第一行和只第二行。这样 set 内只需要存矩形的左右边界和标号。
考虑添加的矩形有哪些情况:如果有被新矩形覆盖的,直接删掉;如果新矩形被某个旧矩形覆盖,直接不考虑新矩形。否则,情况一定只有矩形交而不存在矩形覆盖。具体实现上,对新矩形的行数分类讨论:
假设新矩形为一行,先处理与一行矩形的冲突:新覆盖旧则删掉,旧覆盖新则跳过,出现相交则把新矩形缩短到不相交。结束后,如果新矩形被缩到没有了(),同样直接跳过。接下来处理与两行矩形的冲突:旧覆盖新同样跳过,但新不能完全覆盖旧(行数不够)。如果新在区间上覆盖了旧(即覆盖了旧的其中一行),则将旧的被覆盖的一行删掉,两行矩形改为一行矩形。如果新和旧只相交不包含,则将新矩形缩短到不相交即可。
假设新矩形为两行,先处理与两行矩形的冲突,与1-1冲突相同。接着处理与一行矩形的冲突:新覆盖旧则删掉,旧覆盖新的一整行时,将新矩形改为一行矩形,转到一行矩形处理方式。如果只相交不包含,则将旧的一行矩形缩短到不相交。
By cxm1024
1 |
|
做法二
将矩形离线下来,按左端点排序,依次添加每个矩形,同时维护两行分别能到达的最右端点。由于添加一个矩形时,之前的矩形左端点都不超过当前矩形的左端点,所以只要最右端点超过当前矩形的右端点,则一定被包含。如果当前矩形的某一整行都被包含,则删掉该行,删空则跳过本矩形;如果当前矩形的左端点比两行最优端点的较小值还要小,则改为较小值 ,这样,新矩形和原来的图形最多有一行重叠,将重叠的那一行的旧矩形缩短即可。
By KrK
1 |
|
做法三
我们发现,一行和一行的冲突非常容易计算,两行和两行的冲突和很容易算,复杂的是一行和两行的部分,有较多分类讨论。于是考虑将第三种转化为第一种。
首先同样将所有矩形分成三类,每一类内部可以很方便地处理到不重叠。然后将两行的矩形拆成第一行的一个矩形和第二行的一个矩形,重新处理新的第一行和新的第二行。由于之前每类内部都处理完了,新第一行和第二行的冲突全部为一行矩形和“原两行矩形”的冲突。如果一个包含了另一个,则直接将被包含的删掉:如果删掉的为原两行矩形,则等价于把两行矩形缩成一行矩形。否则则为相交且不包含,由于原两行矩形不方便缩短(需要考虑另一行),所以我们要求让原一行矩形缩短即可。
这种做法虽然在代码实现上较做法二稍长,但分类讨论极少,不容易写错。
By orzdevinwang
1 |
|
做法四
思路与做法三类似,但实现上更为巧妙。
考虑开两个 set 分别维护第一行的矩形和第二行的矩形。实现一个“插入矩形”函数,仅支持插入一个一行的矩形,且产生冲突时优先缩短新矩形而让旧矩形不变(包含则正常删除)。这可以用 set 很轻松地实现。
与做法三相同,在两行矩形与一行矩形产生冲突时,应优先更改一行矩形,对应在这里,则为先插入所有两行矩形再插入所有一行矩形。对于两行矩形,只需要将其拆成两个一行矩形插入,该插入函数自然会正确处理冲突。然后依次插入一行矩形即可。统计答案时要注意两行矩形如果有一行被包含、删除了,则改为一行矩形输出。
By yuto1115
1 | template<class T> |