CF 杂题

代码力量

感觉数数练差不多改练杂题了。

2026.7.1

Cube Snake

思路:3mins45s

2700 在于代码难度。

注意到可以用 \(k \times k \times (k + 1)\) 的矩形包含 \(2\)\(k \times k \times k\) 的正方形,设这一段值域为 \([l, r]\),那么两头的 \(k \times k\) 的正方形值域显然为 \([l, l + k ^ 2 - 1]\)\([r - k ^ 2 + 1. r]\)。然后中间可以出现一个 \((k - 1) \times (k - 1) \times k\) 的子长方体,分治即可。

代码不会写。嘴了。llj play

Tree Queries

AC:?

跨度为 1 天不好计时。

对于操作一假设点为 \(p\) 加了 \(d\),设其子树大小为 \(siz_p\) 点集为 \(sub(p)\),那么对 \(\forall x \not\in sub(p)\) 应有贡献 \(\frac{siz_p}{n} \times d\),对自己有贡献 \(d\),由于是单点查我们可以用树状数组维护。现在考虑计算对儿子的贡献,对于儿子集合 \(son(x)\),对于 \(\forall s \in son(x)\),对 \(\forall x \in sub(s)\) 有贡献 \(\frac{n - siz_s}{n} \times d\)。对每一个儿子的子树直接算会 T,我们不妨树剖,对于重儿子,我们将其子树对应的树状数组区间直接加上贡献;对于不是重儿子,可以在 \(p\) 上打标记,然后每次算答案跳重链算标记的贡献。做完了,具体细节看代码。

code

2026.7.2

Minimum Array

思路:41mins16s

AC:1h35mins48s

强势大炮打蚊子。

扫描线。对 \([1, n]\) 每个位置扫,用一个数据结构维护,第 \(i\) 个位置的值表示 \(i - 1\) 次操作后与原数组的变化量。由于要求字典序最小,将除开最小值的位置都删掉,\(1\)\(n\) 扫一遍即可。由于要支持删位置和区间修改,用 fhqtreap 维护即可,具体细节看代码。做完了。

code

DZY Loves Strings

思路:9mins27s

AC:39mins47s

均摊舒服捏。

先预处理出每个长度在 \(4\) 以下的子串的位置,放在 vector 里。对于每一个询问,先判断是否无解,两个如果有一个不存在于串中即是无解。然后再判断是否包含,包含直接输出。然后对于其他情况,分别枚举两个串的结束位置,然后去二分最近的另一个串,利用这个方法求出最小长度,然后对询问记忆化即可。

这样子均摊 \(O(n \sqrt n \log n)\),最坏情况是 \(\sqrt n\) 个不同的 \(\sqrt n\) 长度的串。做完了。

code

K-Set Tree

思考:1h8mins

什么叫我拆了一堆贡献做不出来但是直接做就做完了???

2026.7.3

Arkady and a Nobody-men

思路:1mins18s

AC:30mins22s

草阿威罗赢了。

我们注意到对于一个点的答案只会有深度小于等于自己的点有贡献,于是我们可以从小到大枚举深度。每次枚举到一个深度 \(i\),枚举每一个点 \(x\),我们发现其答案就为其所有祖先的 \(siz\) 之和,\(siz\) 表示子树中深度小于等于 \(i\) 的点数。先枚举每个点将其所有祖先的 \(siz\) 给加 \(1\),然后再枚举一遍每个点算其所有祖先的 \(siz\) 之和记为 \(sum\),那么其答案就应为 \(sum - i\),因为要减去自身的贡献。我们发现这些操作用可以用树剖线段树维护做到 \(O(n \log ^ 2 n)\),做完了。

code

Converging Array (Easy Version)

思考:1h6mins52s

性质基本找完了但不会,为什么呢,可能是不是很擅长充要条件的计数吧。

这种题先观察性质:

  • 选择了 \(i\) 位置操作后,\(a_i + a_{i + 1}\) 不变,直接算证明是简单的。
  • 对于 \(a_{i + 1} - a_{i}\) 在收敛后应大于等于 \(b_{i}\),证明显然。
  • \(\sum_{k = 1} ^ i a_k\) 单调不增,因为对于操作选择的位置为 \(p\),如果 \(p < i\) 那么和显然不变,若 \(p = i\) 减小或不变。

知道这三个其实就可以计数了。对于 \(\sum_{k = 1} ^ i a_k\),其显然有一个范围区间设为 \([l, r]\),由于性质 2 应有 \(l = \sum_{k = 1} ^ i (x + \sum_{j = 1} ^ {i - 1} b_j)\),题目可知 \(r = \sum_{k = 1} ^ i c_k\),那么和在这个区间内不管怎么选每个 \(a_i\) 最后都应是合法的,直接背包 dp 计数即可,答案就是 \(\sum_i dp_{n, i}\),做完了。

code

Two Arithmetic Progressions

思路:2mins25s

AC:23mins44s

这是什么难度。

用 exgcd 算出特解然后用不等式算一算范围即可。

code

Mahmoud and Ehab and yet another xor task

思考:1h

666 原来是线性基啊,之前对线性基的理解还是太浅了。

线性基。把询问离线下来,从小到大枚举 \(l\),设我们枚举到了 \(i\),那么就把 \(a_i\) 插入到线性基中。对于 \(l\)\(i\) 的询问 \(x\),我们记 \(t\) 表示线性基中非 \(0\) 元素个数。首先判断是否有解,是简单的,设线性基中最高位为 \(k\) 的数为 \(c_k\),从高到低枚举位数 \(d\),若 \(x\) 最高位为 \(d\) 的话就 \(x \gets x \oplus c_d\),最后如果 \(x \ne 0\) 就无解。对于有解的情况,由于线性基的唯一性,随便取基外的元素,线性基内一定有一种取法使得亦或和为 \(x\),那么显然有方案数:

\[2 ^ {i - t} \]

做完了。

code

2026.7.5

Red-Blue Matrix

思考:13mins8s

AC:1h15mins

哈希大法好。

首先对于 \(k\) 左边的数为蓝大于红很烦,我们把左边的数从 \(x\) 变成 \(10 ^ 6 + 1 - x\) 就变成和右边一样的了,都是所有红小于蓝。我们分开处理两边。

对于左边,枚举 \(k\),我们设 \(mn_i\) 表示第 \(i\) 行在 \(k\) 左边的最小值,\(mx_i\) 同理,于是我们枚举蓝色块中最小的值所在的行,即枚举 \(i\) 使得 \(mn_i\) 为蓝色块中最小值。如果其合法,那么要满足不存在 \(j\) 使得 \(mn_j < mn_i \le mx_j\),利用差分和树状数组可以判断。对于每一个 \(k\) 开一个布尔哈希表 \(vec\),并给每一行赋一个随机哈希值(在枚举之前)。对于每一个合法的 \(mn_i\),显然对于满足 \(mx_j < mn_i\)\(j\) 都应被染成红色,把所有这样的行的哈希值亦或起来,假设为 \(h\),那么 \(vec_{k, h} \gets 1\)

然后处理右边并输出。还是同理,设有 \(mn_i\)\(mx_i\),第一维枚举 \(k\),枚举 \(mn_i\) 为蓝色块中最小,同样应满足不存在 \(j\) 使得 \(mn_j < mn_i \le mx_j\),并对合法的 \(mn_i\) 算出其哈希值 \(h\),如果 \(vec_{k, h} = 1\),那么显然就是合法的,输出即可。

做完了,时间复杂度 \(O(nm \log V)\),其中 \(V\) 为值域,具体细节看代码。

code

Permutation

思考:31mins31s

咕咕嘎嘎!

我们从小到大枚举 \(i\),为了方便表示设 \(x = a_i\)。我们在值域上,设 \(p_{a_{\forall j \le i}} = 1\), 其他都为 \(0\),如果不存在 \(x\) 为等差数列 \(3\) 个数中间的那个数,那么 \(p\) 应为以 \(x\) 为中心的回文串,用线段树加哈希维护即可。做完了,细节看代码。

code

2026.7.6

76767676767676

Serval and Music Game

思路:4mins13s

AC:1h17s

你是凑企鹅你是凑企鹅你是凑企鹅你是凑企鹅你是凑企鹅!你是谁啊?🐧🐧🐧🐧🐧🐧🐧🐧🐧

我们枚举 \(x\),设 \(a = \lfloor \frac{s_n}{x} \rfloor\)\(b = \lceil \frac{s_n}{x} \rceil\),那么我们注意到,对于 \(\forall k \in N ^ +\),对于 \(s_j \in [a \times k, b \times k]\) 都是有贡献的,那么我们开一个前缀和的桶来算区间有多少个 \(s_j\),然后直接枚举 \(k\) 做就做完了。注意当 \(a \times k \le b \times (k - 1) + 1\) 时出现了区间相交,那么对于区间 \([b \times (k - 1) + 1, s_n]\) 都应该是合法的了。虽说时间复杂度为 \(s_n \ln s_n\) 并且 \(s_n\)\(10 ^ 7\) 级别,但还是跑得很快。

code

Editorial for Two

思路:6mins25s

AC:1h

卡常卡疯了。

首先注意到答案具有单调性,于是考虑二分答案,现在考虑 check 函数怎么写。假设我们二分到的答案为 \(mid\),我们可以枚举断点 \(i\),设左边最多有 \(a\) 个数的和小于等于 \(mid\),右边有 \(b\) 个数,那么如果存在 \(i\) 使得 \(a + b \ge k\) 那么说明 \(mid\) 是可行的。快速求 \(a\)\(b\) 可以用主席树,时间复杂度为 \(O(n \log n \log V)\),其中 \(V\)\(\sum_i a_i\) 的值域,只需卡亿点点常就过啦。

code

2026.7.8

78787878787878787878787878787878787878787878

Rowena Ravenclaw's Diadem

思考:13mins11s

AC:28mins50s

本质 1500。

首先给出简化版题意:给定一个边权为 \(0\)\(1\) 的森林,每次询问:

  • 对于类型 \(1\),判断 \(u\) 是否是 \(v\) 的祖先且 \((u, v)\) 之间的路径全为 \(0\)
  • 对于类型 \(2\),判断 \((u, v)\) 是否满足 \((u, lca(u,v))\) 的路径全 \(0\)\((v, lca(u,v))\) 的路径全 \(1\)
  • 要注意自己不是自己的祖先,虽然 \(lca(u,v)\) 可能是 \(u\),并且对于路径 \(\forall x \rightarrow x\) 路径和为 \(0\)

好了,你应该已经会了。利用前缀和和倍增,可以快速算出一个点到某个祖先的距离以及两个点的 lca,直接做即可。

code

Strange Sorting

AC:?

忘计时了qwqwqwqwqwq

倍增。对于每个询问,我们先模拟一遍对于一个 \(1\)\(k\) 的子数组,经过一次变换之后到的位置,直接排序就可以得到。假设 \(u\) 经过一次变换后位置在 \(v\),设 \(nxt_{i, j}\) 表示 \(i\) 在经过 \(2 ^ j\) 次变换后在 \(1\)\(k\) 中的位置,由于窗口一直在右移,应有 \(nxt_{u, 0} \gets v - 1\),对于 \(j > 0\) 的项倍增预处理即可。对于询问每一个点 \(i\) 经过变换后的位置,其第一次变换在子数组中的位置 \(p\) 应为 \(\min(i, k)\),那么其最多会被变换 \(mxt = n - k + 1 - (i - p)\) 次。我们假设变换 \(mxt\) 次后相对位置为 \(pos\),若 \(pos\) 不为零那么说明其确实经过了 \(mxt\) 此变换,则变换后的位置就应为 \(i - p + pos + mxt\);否则,其变换次数应小于 \(mxt\),倍增找到其变换次数 \(t\) 和最终位置 \(pos\) 满足 \(nxt_{pos, 0} = 1\),其变换后位置就应为 \(i - p + pos + t\)

做完了,具体细节看代码。

code

Inverse Transformation

思考:53mins27s

asdfasdfasdf

LaZyTaG

Timofey and remoduling

AC:\(\infty\)

随机化与数据分治。

我们可以枚举首项 \(a_i\),设其为 \(x\),通过公式可以算出 \(d = \frac{\frac {2\sum_i a_i} n - 2x} {n - 1}\),那么多次随机取一个随机的 \(j \in [1, n)\),检查 \(a\) 中是否存在 \(x + j \times d\),没有就说明不是答案。这是一个十分优秀的随机策略,每个首项随机个一两千次就可以稳定的通过 54 个点,剩下的数据分治。做 完 了。

code

posted @ 2026-07-02 08:13  ACehomoxue  阅读(14)  评论(0)    收藏  举报