26-02
CF
CF666E
依旧串串。最大值感觉很难做哎?能不能根号分治一下。依旧不会。是不是可以对于模式串建出 GSAM,然后依旧扫描线。把询问挂到 \(p_r\) 上去,扫描线的过程中就用 \(s\) 在 GSAM 上匹配,然后对于每种询问就不断在 \(\text{link}\) 树上往上倍增跳到长度合法的状态。然后就转化成了对于每一个状态,需要求出 \([l, r]\) 区间内的最大的 \(\text{endpos}\) 集合。发现可以用权值线段树+可持久化线段树合并维护。
CF1037H
考虑询问如果是全局的该怎么做。对 \(s\) 建出 SAM,然后把每次询问的 \(x\) 丢到 SAM 上去匹配。贪心的考虑,如果中间失配,就选取最小的可走的转移走,然后输出。否则,在走完之后取最小转移边,然后输出。
如果询问不是全局,可能就有一些套路的 \(\text{link}\) 树上的内容了。考虑在非全局的询问下,如果走到一个位置失配了,那么该怎么办。首先肯定是用可持久化线段树合并维护 \(\text{endpos}\) 的位置,然后如果走到的位置没有在给定区间内的 \(\text{endpos}\),是不是就可以直接弃掉了?似乎很是的样子。因为这么短的没有,长的肯定更加没有了。
全局的做法有点假了,感觉还得在 SAM 上做一遍 DAG 上的 DP 预处理一下?用 bitset 维护?似乎不用了,在转移时用线段树查询一下就 ok 了。
问题很大,因为求的是严格大于的字典序。这倒也无关紧要,特判一下就行了?总的来说,答案不会超过 \(2\times 10^5+q\)。
CF2193H
考虑简化问题,把所有的点权改成 \(0\) 和 \(1\)。然后如果删掉一个点 \(0\),将不会对与其相连的点有影响;如果删掉一个点 \(1\),则与其相连的点的 \(S\) 都会取反。
如果一个点在初始的情况下不满足条件,即不能被删除,那么后续必然会对与其相邻的权值为 \(1\) 的节点操作奇数次,再将其删除。否则,该节点可以在操作了偶数次 \(1\) 或任意次 \(0\) 之后删除。
删除的顺序不好考量,但是可以确定的是,最后剩下来的孤点权值都是为 \(1\) 的。
换句话说,在重构了点权之后,\(S\operatorname{xor} a_i=1\) 的点都是能被删掉的。同时,可以发现,初始状态下能被删的 \(0\) 优先删了一定是最优的。然后发现接下来会出现森林,若每一个森林里都有一个能删的 \(1\) 就一定可以删完。这个结论是错的,因为有 \(0\) 的存在,但是我们可以不考虑 \(0\),将森林进一步细分。为什么一个连通块里有一个能被删的 \(1\) 就能删完呢?因为删掉这个 \(1\) 后旁边的不能删的点的状态就会取反,变成能删了(此时的连通块是去除所有的 \(0\) 后的连通块)。然后对于每一个初始情况下不能被删掉的 \(0\),若在删除过程中有一刻变成了能删掉,直接删就行了。
接下来考虑如果一个连通块里有多个可以被删的 \(1\) 怎么办。手玩发现,如果一个连通块里有奇数个可被删的 \(1\) 就能被删完,否则不行。
删的过程 \(\text{bfs}\) 实现即可。
完了,删除的过程假了。不能用朴素的搜索实现?
结论错了,是连通块大小为奇数就一定能删干净。优先删叶子节点竟然是对的???
CF235C
考虑对 \(S\) 建出 SAM,然后每次将询问的 \(x_i\) 复制两份少一个字符,丢到 SAM 上去匹配。需要注意的是每次的匹配到的长度都只能是 \(|x_i|\)。所以我们只需要对 \(S\) 的 SAM 求一下 \(\text{endpos}\) 集合的大小就行了。
CF696D
感觉很是 \(\text{ACAM}\) 上的 \(\text{dp}\) 了。但是,谁家好人 \(l\le 10^{14}\) 啊!
tag 很有道理,不会是矩阵加速优化吧。先考虑朴素的 dp。设 \(f_{u, i}\) 表示走到 \(\text{ACAM}\) 上的点 \(u\) 且当前已经情话字符串长度为 \(i\) 的最大答案。转移就是刷表,\(w_u\) 可以在建 \(\text{ACAM}\) 时顺便处理出来:
数据范围让人联想到邻接矩阵快速幂啊,而且这不正是经过 \(l\) 条边的最大值吗?然后把点权转成边权不就搞定了吗?easy……
CF587F
建出 \(\text{ACAM}\),则对于每一个询问就相当于,在 \(\text{fail}\) 树种每一个 \(s_i\) 的终止节点的的子树里 \(+1\),然后查 \(s_k\) 的所有节点。
发现直接做很难做,同时数据范围放了根号做法,考虑根号分治。
若 \(|s_k|\ge B\),则这样的 \(s_k\) 只有 \(O(\frac{\sum|s_i|}{B})\) 个,可以直接对于每一个 \(s_k\) 线性暴力地去做。
否则,直接用树状数组维护子树加,然后暴力在 \(\text{fail}\) 树上查链的贡献。
记 \(m=\sum |s_i|\),平衡一下,当 \(B\) 取 \(\frac{m}{\sqrt{q\log m}}\) 时最优。总时间复杂度是 \(O(n\log m+ q\log q+m\sqrt{q\log m})\)。
LG
P5218
由裴蜀定理扩展形式可以直接将这题转化为求若干数的 \(\gcd\) 为 \(1\) 的情况。即:
莫反:
改变枚举顺序得:
杜教筛+整除分块即可。
P14400
推式子推傻了后可以来做一做清新分块。
观察到每一个数只可能被前面的比起小的数替换,考察这个东西的更具体的性质。它只会有可能被 \([S_i, j]\)(\(j\) 为其下标)的比其小的最大值替换掉。不满足区间可合并性,考虑分块。
对于同一个块内,因为我们只需要关注结果,不需要关注过程,所以想办法搞一搞。类似由乃的 OJ 那题,对于每一个块预处理出每一个数在经过这个块后会变成什么数。发现每次变化都会在前缀最大值的地方变化。所以我们只需要找到每块最后一个前缀最大值,然后判断其是否比给定的数大。散块直接暴力模拟就行了。
现在的问题在于如何支持修改。原来 \(q\) 那么小啊,那就可以 \(q\sqrt{n}\log n\) 了。考虑到整块只需要考虑块内最大值,而散块则需要暴力模拟一下。思考这个模拟过程,发现只有比当前数值 \(x\) 要大且处于给定区间的数才能有贡献,且每次必然是最前的数有贡献。所以考虑对每一个块都开一个权值线段树,但是这怎么处理末尾散块的情况。
突然发现既然每次进去都会变成最大值,那么散块也直接查询最大值就行了。问题此时转变成怎么在修改之后处理出散块中的数的值。考虑重构,但是我不会啊。有一个暴力模拟的方法,对于每一次有数经过这个块就将其记录下来,然后用小根堆存储。观察操作的本质会令每一个位置被最小的数占据,所以在重构时用小根堆模拟这个过程。每遇到一个比堆顶大的数就将那一个数压入堆,并弹出堆顶,这样就重构对了。
时间复杂度是严格的 \(O(q\sqrt{n}\log n)\)。
P6055
一顿捣鼓之后推出这个东西:
杜教筛启动。
艹,式子推错了啊。
观察到 \(j\) 等价于是 \(jp\) 与 \(jq\) 的最大公因数,所以原式可以改写成:
于是乎:
依旧莫反:
改变枚举顺序:
整除分块加杜教筛就行了:
P2257
形式化题意:
枚举最大公因数然后莫反得到:
令 \(T=dk\),就有:
容易发现后半部分是可以预处理的,于是整除分块做完了。
P3704
随便乱推套点莫反得到(钦定 \(n<m\)):
套路地整个 \(T=kd\) 出来得:
可以把 \(\mu\) 和 \(f\) 丢到一起去预处理一下,然后剩下的直接整除分块就行了。
P1447
推式子,看着就很仪仗队。
观察结论,发现每个点的贡献为横纵坐标最大公因数乘二减一(不妨钦定 \(n<m\)):
上个欧拉反演:
枚举 \(d\) 得:
直接套整除分块就行了:
跑得还没线性做法快。
P3735
考虑刻画两个相等的串,即为拥有公共前后缀,然后非最长公共前后缀的长度不超过 \(k\)。
想到建一个 SAM。
考虑如果知道了一个模式串的每一个后缀在文本串中的 \(\text{endpos}\) 那会不会好做一点。这样就只需要判断前缀了。前缀的判断应该是可以直接丢到 SAM 上跑出来的。
对于模式串 \(s[1:i]\) 与 \(s[i+1:n]\),若 \(s[i+1:n]\) 已经跑出来了在文本串 \(t\) 中的 \(\text{endpos}\)。考虑查询有多少个能与其相匹配的前缀。这些前缀需要满足的条件就是与该后缀的长度之差 \(\le k\)。
感觉这样很难做。
注意到可以强行将失配的部分补成 \(|k|\) 的长度。于是可以提前在 \(s\) 中将要匹配的区间都预处理出来,在 SAM 里进行一些标记。套路地,在询问的 \(t_i\) 中也这样枚举划分点。
改成 ACAM,正串反串都建一个,然后把每一个划分点的节点都标记并建立映射,在 \(\text{fail}\) 树上 BIT 维护扫描线就行了。有重,所以需要容斥,用长度为 \(k\) 的减去长度为 \(k-1\) 的就对了。
调不出来,咕着。
P1829
形式化题意:
经典转化:
考虑改变一下顺序,先枚举 \(\gcd(i, j)\),得到:
尝试对其应用莫比乌斯反演:
改一下求和顺序得到:
观察形如如下式子的贡献:
\(G\) 函数便是等差数列求和,所以原式变成了:
枚举乘积 \(kd=\ell\) 并转化求和顺序得:
设函数:
容易观察到 \(F\) 是一个积性函数,所以可以线性筛预处理,然后再用整除分块即可。
P2522
形式化题意为:
先对原式进行容斥,然后每一部分都形如:
显然 \(i\) 和 \(j\) 都必须是 \(k\) 的倍数,不能包含其它的公因数,所以有:
尝试对其应用莫比乌斯反演,得到:
交换求和顺序:
后半部分很典,可以整除分块处理,即:
于是线性筛预处理 \(\mu(d)\) 然后整除分块处理就行了。
时间复杂度为 \(O(V+n\sqrt{V})\),其中 \(V\) 是值域。
P2260
服了,纯推式子的题目。
上几个整除分块就行了。
P3935
题目需要求 \([l, r]\) 中每一个数的因数个数之和。
注意 \(f\) 是积性函数,即满足当 \(\gcd(i, j)=1\) 时有 \(f(i \times j)=f(i)\times f(j)\)。
屁用没有,考虑转化拆贡献,则原式变成:
形如整除分块形式,这就能做了。
P8368
\(T_0,T_1,T_2\) 似乎没什么观察。但注意到从 \(T_3\) 开始后,\(T_i\) 与 \(T_{i-1}\) 必须拥有长度为 \(i-2\) 的公共前后缀。由 \(T_i\) 向 \(T_{i+1}\) 的转变就是删掉第一个字符,然后添加两个字符,这样第二、三个条件就都满足了。
但是感觉很困难啊。考虑能不能 DP。发现答案的下界为 \(\lfloor\frac{n}{2}\rfloor\),因为有显然的倒着构造的方案 \([i, j], [i-1,j-2], [i-2, j-4]\cdots\)
考虑能否从 \([i_1,j_1]\) 回到 \([i_2, j_2]\),满足 \(i_1<i_2,j_1-i_1=j_2-i_2+1\)。如果可以回到,那么答案就有可能更大。相当于长度为 \(i_1-j_1、\) 长度的子串出现了至少两次。所以需要维护一下每种子串的出现次数,这就可以 SAM 维护。对于每一个状态取 \(\text{maxlen}\) 计算答案,最终 \(ans\leftarrow \max\{\text{maxlen}+\lfloor\frac{n-r}{2}\rfloor\}\)。
P6816
观察到题目等同于找一个子串,然后每次用子串的一个后缀去覆盖,同时,每次覆盖时子串的非后缀部分为其 \(\text{border}\) 的一部分。倒不一定,因为最后一个覆盖显然有可能会超出范围。
考虑到一个事情,只需要建出 SAM,然后使得 \(\text{endpos}\) 与 \(\text{endpos}\) 之间的长度不超过 \(\text{len}\),那么肯定是一个合法的答案。故对于每一个 SAM 状态,答案一定形如一段以 \(\text{maxlen}\) 开头的区间。然后剩下需要做的便是 check 第一个 \(\text{endpos}\) 前和最后一个 \(\text{endpos}\) 后的子串合不合法。前缀的判断是容易的,只需要在 \(\text{link}\) 树上查询从根到当前状态最前的 \(\text{endpos}\) 的最后位置,如果有交,那么合法。对于后缀的判断能否考虑对反串建 SAM?
似乎是可以的,每次在反串的 SAM 上倍增找到合法的状态,然后按上面的方法进行查询。
接下来考虑如何找字典序最小的子串。考虑在 SAM 上遍历查找的话有没有什么性质,即如果走到一个状态 \(u\) 不合法,那么其转移到的节点是否也就都不合法了。发现这个东西是假的。
停停停,原来是求的最短的 \(s\),然后再字典序最小啊!最短的 \(s\) 是容易的,还是考虑字典序最小有没有什么性质。
原来字典序可以二分+hash?
好难啊,先咕着吧……
P3426
注意到操作等同于每次添加所选子串的一个后缀,且子串长度减掉后缀长度 \(\le |\text{border}|\)。考虑跑一边 KMP 把前缀函数先预处理出来。同时注意到印章穿一定是原串的一个 \(\text{border}\)。ok,先学失配树,再来挑战这题。
又注意到一个东西,每次拼接相当于是把原串的一段 \(\text{border}\) 进行拼接(但事实确是将其重叠然后将剩余部分拼接),所以和 KMP 关系非常大。然后进行一个神秘的 DP,设 \(f_i\) 表示前 \(i\) 位的最短印章,则显然这东西只能等于 \(f_{\text{border}_i}\) 或 \(i\),考虑判断这个东西什么时候选前者。
发现需要存在一个点 \(j\),使得 \(s[1:j]\) 能被 \(f_{\text{border}_i}\) 覆盖且 \(j\ge i-|\text{border}_i|\)。实现是容易的。
P5999
转换题意,相当于求长度为 \(n-2\) 的排列个数,使得 \(\forall i,\{a_i>\max(a_{i-1},a_{i+1})\lor a_i<\min(a_{i-1}, a_{i+1})\}\)。
考虑连续段 DP。设 \(f_{i, j}\) 表示插入了前 \(i\) 个数字且当前有 \(j\) 个连续段的答案。转移只可能是合并或新增连续段,然后做完了。
P7967
正难则反,考虑用总数减去能互相吸引的个数,
P9197
显然,如果朴素 dp 需要状压,所以两档部分分都是好拿的。但是!!!数据范围太大了!!!
考虑将 dp 的过程转换为一个从小到大往序列中插入数字的过程。同时,这样可以把绝对值符号给去掉。
已严肃学习连续段 DP。
P5024
写一下朴素的转移式。设 \(f_{u, 1/0}\) 表示以 \(u\) 为根的子树,\(u\) 选/不选的答案。转移如下:
套路地,如果可以用矩阵搞出这个东西,就可以直接用动态 DP 了。改写转移式,设 \(g_{u, 1}\) 表示轻儿子可选可不选且 \(u\) 选的贡献,则第一个转移式简化为(\(f_{v, 0}\) 表示重儿子的贡献):
第二个转移式就变成了:
现在开始推矩阵。设转移矩阵为 \(U\),\(v\) 为 \(u\) 的重儿子,定义广义矩阵乘为取 \(\min\),有:
显然,可以设 \(U\) 为:
则:
所以:
联系转移式得到:\(a=+\infty\),\(b=g_{v, 0}\),\(c=d=g_{v, 1}\)。所以 \(U\) 为:
剩下的东西就很典了。拿树剖和线段树维护这些转移矩阵和初始矩阵,然后每次查询就改一下那两个点的矩阵,再算答案,然后再改回来。
P4094
转换一下题意,每次询问相当于求以 \(c\) 开头的长度不超过 \(d-c+1\) 的串串中在 \([a, b]\) 出现的最长串串。所以考虑离线做一下,把询问都挂到 \(c\) 上去,然后倒着枚举 \(c\)。这样我还是不会做啊!
考虑一个事情,那就是如果把弄一个原串的反串出来,那么每次的询问就相当于是求 \([a, b]\) 这段区间中的状态满足 \(\text{endpos}=c\) 的最长子串。然后你考虑从前往后枚举 \(c\),再对于询问去 check 最长的 \(\text{endpos}\) 序列,但这个东西很不好搞,也不能分治的样子。
观察到答案是有单调性的,具体地说,如果长度为 \(x\) 的 \(\text{endpos}\) 状态不符合答案,那么 \(\ge x\) 就更不会有贡献了。
在 SAM 考虑很难受,直接把询问丢到 \(\text{link}\) 树上观察。发现,求的东西是以 \(c\) 结尾的一系列状态在 \([a, b]\) 区间中的最大值。这样似乎就比较好做了。套路地,用线段树合并维护 \(\text{endpos}\) 的位置,然后只需要找到每一个状态对应的终止字符就行了。最后基排然后拓扑时顺便线段树合并上去。询问就是线段树上二分然后取 \(\max\)。但这样复杂度会爆炸!
考虑对于每一次询问都进行二分答案。然后 check 是否存在一个长度为 \(\text{mid}\) 的子串在 \([a, b]\) 区间内。但是我不会 check?
噢噢噢噢哦哦哦,原来可以在 \(\text{link}\) 树上倍增找第一个满足的状态,搞懂了。所以可以直接用可持久化线段树合并维护 \(\text{endpos}\) 集合,然后二分答案的时候只需要从 \(s[1:c]\) 倍增找到 \(s[c - mid+1:c]\) 所在的状态,然后查询权值线段树以 check 就行了。具体的,就是查询 \([b+mid-1, a]\) 中有没有 \(\text{endpos}\)。
时间复杂度是双老哥的。
P4770
注意到子串问题,考虑建 SAM。同时因为涉及到多次询问,令人想到 GSAM。
考虑一次询问的在 GSAM 上的本质是什么。可以在 GSAM 上把文本串的 \(\text{endpos}\) 集合都标记出来,然后如果这些 \(\text{endpos}\) 集合与查询的 \([l, r]\) 区间有交集且该状态是在此次询问中遇到过的状态,那么该状态肯定没有贡献了;否则,该状态对于此次询问会有 \(\text{len}_p-\text{len}_{\text{link}_p}\) 的贡献。
发现每次询问都这样判断是困难的,而 \(\text{endpos}\) 集合的维护只能通过 bitset 或线段树合并来维护,而 bitset 显然被舍弃了。但线段树合并是不能在线的,所以考虑把询问拆成各个状态对答案的总贡献,然后离线下来通过线段树合并计算即可。
感觉还不算很难?时间复杂度为 \(O((q+|S|+\sum|T|)\log (|S|+\sum|T|))\)。
代码实现稍有些复杂,因为 GSAM 的形态可能因为克隆节点而变换,所以需要等 GSAM 完全建完之后再对每一个串串进行 GSAM 上匹配,然后将询问挂到匹配到的状态上。最后再线段树合并就行了。
不知道是代码写错了,还是思路假了。
考虑一个部分分,当 \(l=1,r=|S|\) 时,如何计算答案。
可以对于 \(S\) 和 \(T\) 都先建出 SAM,然后直接在 \(T\) 上匹配算答案。
然后考虑 \(l\),\(r\) 随机时只需要判断匹配到的一个状态是否出现在 \([l, r]\) 中,以及出现的最长子串的长度。可以用可持久化线段树合并维护 \(\text{endpos}\) 实现。每次对答案的贡献的计算是容易的。
P11287
比较显然的,可以先把所有的关键点删掉,然后把连通块缩成一个点,其点权为连通块里的点的点权和。每次查询就等同于查询与关键点相连的连通块的权值之和就行了。
问题在于如果每次都枚举与关键点相连的点会炸,因为这样不能保证复杂度,可以被卡到 \(O(qn)\)。如何优化?
根号分治,钦定阈值 \(B\)。
- 若关键点 \(u\) 的度数 \(< B\),则直接暴力枚举查询答案。
- 若关键点 \(u\) 的度数 \(\ge B\),则说明这样的点一定不超过 \(\frac{m}{B}\) 个,所以可以对于每一次修改都预处理出这些点的答案。
总时间复杂度为 \(O(q(B+\frac{m}{B}))\),当 \(B=\sqrt{m}\) 时有最优复杂度 \(O(q\sqrt{m})\)。
P3645
为什么降绿了啊???
考虑如果能够图论建模出来就可以 \(O(n)\) 求出答案,只需要 \(\text{bfs}\) 即可。同时注意到连边时复杂度很高,所以可以对于每一个“大楼”都建一个虚点,最后答案再除以二就行了。
图论建模考虑根号分治,钦定阈值 \(B\):
- 若 \(P_i\ge B\),则其能跳到的点不会超过 \(\frac{N}{B}\) 个,可以直接暴力枚举然后连向虚点。
- 若 \(P_i<B\),我不会,看来不能这样做了。
我无语了,状态数大法,第二种最多只有 \(N\sqrt{N}\) 中状态数。所以直接暴力 \(\text{01bfs}\) 是对的。
P3758/P5789
做一下矩阵的题目。
容易写出一个朴素的 dp。设 \(f_{u,i,0/1/2}\) 表示走到点 \(u\) 且为第 \(i\) 轮,且这一轮要进行停/走/爆炸的方案数。
转移平凡的:
这样子的时间复杂度是 \(O((n+m)\times t)\) 的,显然需要优化。考虑建出邻接矩阵,然后进行矩阵加速。具体的,因为可以留在原地,这就相当于从 \(u\) 走到 \(u\),所以在邻接矩阵上给每一个点都连自环。
还是学习一下吧。邻接矩阵 \(A^k\) 表示图上任意两点 \(u\)、\(v\) 经过 \(k\) 条边到达对方的方案数。现在只需要处理自爆这个东西就可以解决这道问题了。有办法了,可以建超级源点 \(0\),让每一个点都像 \(0\) 连一条单向边,这样便可以实现目的。哦,\(0\) 也要连自环,表示一直兜圈子。
时间复杂度:\(O(n^3\log k)\)。
P8571
请开始你的挑战。
显然肯定是先离线,然后建 ACAM,然后不会了。
受到 CF587F 的启发,考虑根号分治一下。设 \(\sum|s_i|=m\),钦定阈值 \(B\),则:
- 若 \(|s_k|\ge B\),则将 \(s_k\) 的节点在 \(\text{fail}\) 树上标记为 \(1\),然后暴力枚举每一个 \(s_i\),查询其终止状态在 \(\text{fail}\) 树中子树的权值和。然后用线段树维护一下询问。则这部分的时间复杂度为:\(O(\frac{mn}{B}+q\log n)\)。
- 若 \(|s_k|<B\),发现最终答案不会超过 \(B\) 且不同的答案不会超过 \(2B\) 种。所以考虑对于每一个 \(s_k\) 建立虚树,然后如果对于一个虚树上的点 \(u\),若存在 \(u\) 的一个祖先节点且该节点为询问 \(i\in [l, r]\) 区间中 \(s_i\) 的终止节点,则该次询问的答案至少为 \(sz_u\)。故考虑扫描线,把询问挂到 \(r\) 上去,每次枚举虚树中的点查答案就行了。判断是否存在 \(i\in [l, r]\) 只需要维护当前 \(\text{fail}\) 树中每一个节点对应的最大 \(i\)。所以可以用分块维护 \(\text{dfs}\) 序,然后在扫描线的时候将扫到的串串结束位置的子树取 \(\max\),每次询问单点查询。用 \(O(\sqrt{N})-O(1)\) 分块可以做到:\(O(m\log m+n\sqrt{m}+qB)\)。
总时间复杂度为:\(O(\frac{mn}{B}+q\log n+m\log m+n\sqrt{m}+qB)\)。取 \(B=\sqrt{m}\),可以做到 \(O((n+q)\sqrt{m}+q\log n+m\log m)\)。

浙公网安备 33010602011771号