题解:P12608 骷髅打金服

· · 题解

如果这题时限压缩到 1s 就真的是卡常神题了。最大点 566ms,记录一下卡常技巧。

思路

首先可以感受一下出现过的元素出现次数都相等是什么形态。将相同的数放到一行里列出一个矩形,比如:

1 1 1 1
2 2 2 2
3 3 3 3

可以很自然地想到每一列的值都是相等的。判定相等可以使用哈希,将每一个值 x 随机一个权值 qz_x,设每一个值的出现次数为 cnt_x,则判定条件即为 \sum_x qz_x\cdot cnt_x \bmod \sum_x qz_x = 0

但是维护一个值是否出现是比较困难的。因为“出现过”这个信息不可减,所以无法使用前缀和作差的方式。但是这个信息是可加的,所以可以考虑分治。

但是分治后如果两边的数集不相同,还是没法做的,因为需要取并集的过程。那如果两边的数集不相同,有没有什么性质呢?

确实有。假设左边有一个在右边没出现的数 x,那么所有数的出现次数就都为 x 在左边出现的次数 cnt_x 了。进一步地,x 应当是众数,而且在左边出现的数在右边的出现次数就都确定了(对于 y 在右边出现的次数为 cnt_x-cnt_y)。

但是右边还可以有左边没出现的数。此时它也应当是右边的众数,而且出现次数与左边的众数应当相同。

这两种情况是无法合并的,因为右边的众数既可以出现在左边也可以不出现在左边。这就是剩下的情况还需要分三类的原因。大概的框架清楚了,接下来详细讨论一下四种情况。

前三种情况可以使用哈希维护,第四种情况可以在 wz 处记录下来查询并扫描线,也可以使用哈希维护。因此这道题做完了,复杂度为 \mathcal O(n \log n)

卡常技巧

提交记录