MX 练石 2026 NOIP #7

好难好难好难好难,为数不多的罚坐了。

4h20min 怒砍 20pts /oh


2025 --【炼石计划 NOIP】-- 第七套

链接:link
题解:link

时间:4h20min (2025.09.18 13:50~18:10)
题目数:4
难度:

A B C D
\(\color{#FFC116} 黄\) \(\color{#3498DB}蓝\) \(\color{#3498DB}蓝\) \(\color{#BFBFBF} ?\)
*1500 *2300 *? *?

估分:50 + 10 + 10 + 10 = 80
得分:0 + 10 + 10 + 0 = 20
Rank:152/199


场祭

读题。

开 A,发现可以转化为 \(a_i - i \le a_j - j \land b_i - i \ge b_j - j\)。但是要求连通块个数而不是别的什么,感觉很难办。

然后想到了在按照 \(a_i\) 升序排序后,如果 \((i,j)\)\((j,k)\) 都符合条件,那么 \((i,k)\) 一定符合条件,所以可以只把每个点连向它后面第一个 \(b_j\) 比它大的点,以及前面第一个 \(b_i\) 比它小的点。

发现没过大样例,多连几个点乱搞一下试试?输出没有任何改变。

于是开始写拍子。查了查发现排序需要以 \(b_i\) 为第二关键字降序,不过大样例还是没过。

快 2h 了不管了先跳了。

B 看起来是细节题,感觉连暴力都不会写的,拿了 10pts 特殊性质走人了。

C 暴力 10pts,D 暴力 10pts。

还剩 1h。

尝试去写 B 的暴力但是失败了。尝试去拍 A 但是懒得拍了,感觉做法应该是假的。

罚坐了。哦其实是没事干去水洛谷了。


补题

A 死因:把 connected.in 打成 cpnnected.in,然后 connected.out 还打对了。应该是测样例的时候,把 connected.in 改成了 1.in,改回来的时候打错了导致的(

补 A,注意到在倒序遍历过程中,若 \(i\) 和一个连通块内的最大 \(b_j\) 没有边,那么它一定和这个连通块没有边,所以只需要维护每个连通块内的最大 \(b_j\) 即可。单调栈也是可以维护的,只不过弹栈顶代表的是 \(i\) 和栈顶有边。最后答案也可以不用 dsu 算了,就等于栈的大小。

补 B,哦我甚至连最容易注意到的都没注意到菜完了。

注意到若 \(s_i\) 确定了,那么 \(s_{i+1}\) 也是确定的:

  • \(|s_i| \ge |s_{i+1}|\),显然 \(s_{i+1}\) 只能是 \(s_i\) 的前缀。
  • \(|s_i| < |s_{i+1}|\),那么 \(s_{i+1}\) 一定由若干个完整的 \(s_i\) 拼上一个 \(s_i\) 的前缀组成。

所以只需要确定 \(s_1\),暴力枚举就有 30pts 了(

容易想到去考虑 \(s_{i+1}\)\(s_i\) 的限制,因为也只有这样才可能去确定 \(s_1\) 了。

  • \(|s_i| \ge |s_{i+1}|\),那么 \(s_i\) 的前 \(|s_{i+1}|\) 个字符就必须和 \(s_{i+1}\) 相同,不过顺序随便。

  • \(|s_i| < |s_{i+1}|\),那么 \(s_{i+1}\) 中完整的 \(s_i\) 显然不需要考虑,需要考虑的是 \(s_{i+1}\) 末尾那个 \(s_i\) 的前缀 \(t\),显然 \(s_i\) 的前 \(|t|\) 个字符必须和 \(t\) 相同,同样顺序随便。而且对于一对 \((s_i , s_{i+1})\)\(t\) 是确定的,就等于 \(s_{i+1}\) 中扣掉所有完整的 \(s_i\) 后剩下的字符集。

    形式化地,就是要求 \(s_i\) 的前 \(|s_{i+1}| \bmod |s_i|\) 个字符需要和 \(t\) 相同。

可以发现,两种限制都形如「规定 \(s_i\)\(k\) 个字符所组成的可重集等于 \(P\)」的形式。

考虑是否能将 \(s_i\) 的限制下传(上传?)到 \(s_{i-1}\)

  • \(|s_{i-1}| \ge |P|\),则限制不变,即 \(s_{i-1}\) 的前 \(k\) 个字符也为 \(P\)
  • \(|s_{i-1}| < |P|\),发现和上面 \(s_{i+1}\)\(s_i\) 限制的第二种情况是等价的。即要求 \(s_{i-1}\) 的前 \(|P| \bmod |s_{i-1}|\) 个字符为 \(P\) 中扣掉完整的 \(s_{i-1}\) 后的剩余部分。

那么,就可以通过这种方式,一直把限制下传到 \(s_1\) 了。

但是复杂度不会爆炸吗?

不会的,因为有结论:\(\forall n \in \mathbb N\),进行操作 \(n \gets n \bmod m ~(m \in [1,n])\) 的最多次数为 \(O(\log n)\)。所以一个限制最多被改变 \(O(\log n)\) 次。所以每次只考虑上面第二种情况进行限制的改变即可。

Proof. 分讨 \(m\)\(\frac n 2\) 的大小关系。若 \(m \le \frac n 2\),则 \(n \bmod m < m \le \frac n 2\);若 \(m > \frac n 2\),则 \(n \bmod m = n-m < \frac n 2\)。所以每次操作 \(n\) 至少会减半,则最多操作 \(O(\log n)\) 次。

在写的时候,对于每个 \(s_i\) 预处理一个 \(nxt_i\) 表示上一个比 \(|s_i|\) 短的串,那么跳 \(O(\log |s_i|)\)\(nxt\) 就可以到达 \(s_1\) 或者使得限制的 \(k=0\)(限制消失)。哦实际上这样会有一些没用的操作,因为预处理的是 \(|s_i|\) 而不是 \(|P|\),不过没关系,因为有 \(\sum |s_i|\) 的限制,所以没用的操作不会太多,遇到 \(|P| \le |s_{nxt_i}|\) 的直接不管继续往下跳即可。

但是有一个问题:会不会出现中间有两个冲突的限制被跳过去了,而且并没有传到 \(s_1\),最后就没有被发现呢?

不会的。首先肯定要在构造方案的时候把每个串都确定下来,同时判断无解。而 \(s_1\) 不确定的部分只能是相邻两条限制中间的部分,那既然这部分没有限制,所以它随便排也不会对后面造成什么影响,所以可以认为不存在本质不同的 \(s_1\)。于是构造时判无解就足够了。

但是是真!的!难!写!写 + 调估计得有 4h 了。

C 神必数数题,题解看不懂不补了。


天依宝宝可爱!

posted @ 2025-09-19 07:44  little__bug  阅读(51)  评论(5)    收藏  举报