开始读题没有注意到那个 square,多费了一些功夫。可以在确定 n 是平方数后构造出对应的字符串,然后与给定的字符串比较即可,因为一旦 n 确定,合法的字符串就是唯一的。
C
注意到当 l 和 r 为最大值时对应的答案也才到 4e4,这启发我们可以直接进行暴力求解,从 l 开始,每次将 d 加一即可。
D
感觉 D 要比 E 和 F 更有学习意义,我们发现每次执行i = p[i]这个操作,假使我们将 1 到 n 看作一系列节点,那么 i 与 p[i] 之间就有连边,此时发现整张图其实是由一些环组成的(包括自环),我们只需要对所有点进行遍历,如果它没在某个环中(也就是fa[i] == i),就进入 dfs 找环(这其中有记忆化的思想),环的根就是入口节点。当我们把所有环找出来之后,每个节点最多能到的黑色整数个数就是它所在环的黑色整数个数。
用一种桶状前缀和来存储所有数的出现次数,此时 cnt[i] 表示小于等于 i 的数字在数组中出现的个数。
之后二分答案,在 check 函数中的每一次 i += x 的操作中判断这一段中取余 x 后小于等于 mid 的数有多少。
需要注意的是我们在二分时只能在 res >= pos\\pos为中位数位置 时返回 true,原因和之前博客中二分求第 k 小的 a[i] 时必须 sum >= k的原因是一致的,当我们按值二分时,一般会按照数量进行分类,当我们所求的 k 并不确切是给定数组 a 中一个小于等于某 a[i] 的数的数量时(也就是所求答案值出现不止一次时),我们按照小于 k 和 大于 k 将整个 [min_of_a, max_of_a] 区间分为两部分,此时右区间的左端点符合题意,而左区间的右端点不符合题意。
还有一点是,由于某个大数可能会被查询很多次,为了减小常数,我们可以离线处理 x 从 1 到 n 的结果,这样就能做到 O(1) 查询了(亲测不离线会 t)。
posted on
2024-09-03 14:07wuhu12345
阅读(26)
评论(0)
收藏举报