好像出的有点过于难了。。。。

另外题面有些小锅,非常抱歉。

T1

暴力是容易的,注意到一个位置一旦操作了就不会再操作了。

那么第一次操作后就相当于直接变成了链,这个链是容易做的,一个想法是从左往右操作一遍,最后检查是否有 。这个想法是对的,因为边界只有一个数与它挨着,只能靠这个与它挨着的数变成

于是有了一个 的做法。

考虑优化,首先把链复制一份放在后面,断环成链,那么只需要检查每个长度为 的子区间是否合法即可。

如何判断一个子区间合法呢?首先先操作一下这个子区间的头和尾,然后就变成了一条链,设链上第 个数为

考虑一个长度为 的链合法的充要条件:

  • 奇数位置上的数和=偶数位置上的数的和。

  • 对于

第二个条件发现可以写成前缀和的形式。

于是正解做法就出来了,维护一个奇数位置的前缀和,偶数位置的前缀和,然后需要查询的是一个长度为 的区间最小值,使用单调队列即可。

时间复杂度线性。

T2

这题不是我出的,是我同学出的,所以我就没怎么管这题。但是数据好像造水了,暴力冲过太多分了。。。非常抱歉。

 先固定 , 分析取到最小值时 的性质. 注意到 的大小取决于 的最高不同 bit. 记 表示 的最高 bit, 可以猜测, 当 取到最小时, 必然有 取到最小.

  接下来, 我们来证明这个结论. 设 , 注意到

因而

, , 那么

利用这个结论, 设 , 我们只需要考虑 对答案的贡献. 另一方面, 由于此时 , 所以本质不同的 只有 种, 对应着最低的 个 bit 的不同取值. 我们只需要求出这 个答案即可, 而不必考虑所有的 个值.

  另一个更有趣的事实是, 直接枚举计算答案的复杂度是有保证的.

  证明也很简单, 的高 个 bit 仅有 种取值, 而当这些 bit 固定时, 最多仅存在一对满足条件的 (否则, 由鸽巢原理, 的值会减小). 对于这 , 我们 地枚举每个 计算答案. 最终复杂度为 .

  此外, 对于 的求解, 只需要桶排 之后取 的最小值即可. 此后仅对 枚举 贡献答案. 注意不要直接排序或引入 Trie 树, 我尽力卡掉了.


  为什么 ? 因为再大的话输入就比排序还慢了, 没有办法精准毙掉带 做法.

T3

居然只过了 1 个人,有点意外。

个人认为算是比较套路的 dp 题吧。

首先得搞清楚如何快速求出最大子段和,方便设计状态,设 表示以 为结尾的最大后缀和,那么最大子段和就是所有 的最大值,只需统计所有 的方案。

的转移是 easy 的,

于是就可以设计 dp 了,一个很显然但又非常关键的性质:在对 个位置加 后, 的变化量是 的。

表示选择到了 ,一共选了 个位置,新的 ,转移是很简单的。讨论第 个数加不加 ,计算出新的 ,然后转移即可。

优化也是简单的,观察转移可以发现本质上是一个区间平移后相加的过程,由于模数为 ,使用 bitset 优化即可。时间复杂度 ,不卡常数。

T4

考虑对 集合中的串长根号分治,设阈值为

如果 ,考虑对其先建出一个 AC 自动机,先来看询问怎么做,如果 ,直接暴力,否则可以发现只有 这一段可能会超出去,于是这一段就暴力做, 就直接查一个区间和。 有修改怎么办呢,考虑到修改是单点修改,相当于是在 AC 自动机上进行一个子树加,然后 需要 查,于是使用 区间加, 单点查就行。发现 这一段的和并不好维护,因为一个修改可能影响很多个地方的值。可以转化为以下问题:

两个序列,下列两个操作:

  • 对于所有满足

  • 查询

考虑对序列分块,可以想到的是对块内的 先排序,那么修改整块就直接在块内二分找到满足条件的区间,去维护块内的和,散块暴力重构,查询就整块直接加上维护好的整块的和,散块暴力加,需要通过二分找区间。不能暴力预处理前驱后继,否则空间就爆炸了。出题人没有刻意卡带 log 的做法。纯根号可以考虑分散层叠,但是因为分散层叠要满足每个数只能出现一次,即 中不能有相同的数,但是实际上 串的每个前缀可能对应的是同一个位置。但是没有关系,不如反过来,做如下问题:

  • 对于

  • 查询

可以发现上下两个问题是等价的,但是下列问题在本题中有一个特殊性,满足 序列互不相同,这样子可以直接使用分散层叠了。

如果 ,这种大串只有 个,考虑直接对每个大串求出其在 串的 endpos 集合。但是暴力求是 的。考虑 bitset,先给这些大串同样建一个 AC 自动机,然后把大串挂在 fail 树上,对于 串的每一个前缀 ,找到 fail 树上其所对应的结点 ,然后把 先贡献到从 到 fail 树的根这条路径上第一个有大串对应的结点。然后对这些大串挂在 fail 树上的节点的集合建一个类似于虚树的东西(只需要找到每个点有大串对应的第一个祖先就行)

,然后自底向上做一遍 bitset or。这样子做就是 的。考虑如何查询,如果直接存 个前缀和数组,空间就爆炸了,由于强制在线所以也不能离线处理。

考虑时间与空间的平衡,先把 序列每 个分一块,预处理出一个 表示第 块中, 的值。然后再对 序列每 个分一块,预处理出整块的前缀和。 查询就很简单了,散块暴力查,整块直接查。

这个做法的常数巨大,需要精细实现,并调块长。

,复杂度为