无内鬼,来一发和 ACAM 解法并无本质区别的 SAM 解法(
首先把询问差分成两个参数 r,k,并考虑两个子问题:
若每次询问的 |sk| 之和较小。
将询问对 r 排序,在 Parent Tree 上把每个 si (i≤r) 对应的状态的子树加一,枚举 sk 每个前缀对应的状态并求和。
相当于反向统计 |endpos| 之和 —— 计算每个结束位置上有多少串造成贡献。若 q 较小。
将所有 sk 的每个前缀对应的状态在 Parent Tree 上加一,并求子树和,即求每个状态在每个 sk 中的的 |endpos|。
同样将询问对 r 排序,对每个 si (i≤r) 对应的状态求其在 sk 中的 |endpos| 之和。
考虑设一个阈值 T,若询问的 |sk|≤T,则做第一个子问题,否则做第二个子问题。
若忽略第一个子问题中数据结构的复杂度,两部分复杂度分别为 O(nT+n2T)(假设 n,q,∑|si| 同阶)。
显然当 T=O(√n) 时取最优复杂度 O(n√n)。
再来考虑第一个子问题中的数据结构,注意到共有 O(n) 次修改和 O(n√n) 次查询,使用分块做到 O(√n) 单次修改和 O(1) 单次查询即可。
总复杂度依然为 O(n√n)(时空常数极大)。
代码:
1 |
|