字符串问题
Xenia and String Problem
考虑由于好串的定义,导致长度一定为 \(2^i-1\),所以总数是 \(O(n\log n)\) 的,考虑像构建 st 表一样求出所有好串。
修改一个字符看做先删再加,删会导致所有包含这个字符的好串无效,加的贡献分为三种情况。
-
左右合法且相等,中间字符出现次数过多。
-
左右合法,但是不相等,发现只有左右的中心不同才可能有贡献,检验可以看左右 lcp 长度是否符合条件。
-
左右有一个不合法,修改后可以相等,考虑左右的是否仅在那一个点出不同,可以求 lcp 检验。
答案就是不变的 ans 加上最多能使 ans 增加多少。
求 lcp 可以 SA 预处理,总复杂度 \(O(n\log n)\)。
Bosco and Particle
一个对撞机可以取它的最小循环节代替,每个对撞机是独立的,所以对于每个对撞机先求出向左和向右的次数的比值 \(\frac{a_i}{b_i}\),并且找到最右的有用的对撞机,设一个空隙被经过的次数是 \(f_i\),则 \(\frac{f_{i-1}}{f_i}=\frac{a_i}{b_i}\)。
因为 \(f_i\) 都是整数,所以以 \(f_0\) 为主元,得到最小的合法 \(f_0\),递推出其它 \(f_i\),加起来乘二得到答案。
Fedya the Potter Strikes Back
对于每一个新加的字符,算出包含它的 border 的贡献,加上原来的即可。
求 border 用 kmp,由于每次最多加入 \(1\) 个 border,所以总数是 \(O(n)\),接下来考虑如何快速定位需要删去的 border。
一个 border 会被删去当且仅当它前半部分后面的字符不等于 \(c\),所以记录 \(top_i\) 表示第 \(i\) 个 border 前第一个与它下一个字符不同的 border 是第几个,均摊 \(O(n)\)。
border 的贡献是区间 \(w_i\) 最小值,所以用单调栈维护,每次将剩余贡献大于 \(w_i\) 的 border 贡献调整,因为一次会合并所有贡献大于 \(w_i\) 的数,所以用 map 维护均摊 \(O(n\log n)\),删 border 的时候要记得在 map 中减去。
答案可能爆 long long,分成两部分存储即可。
Twilight and Ancient Scroll
将每一类字符串排序后,有一个显然的前缀和优化 dp 做法,因为需要比较两个不同类的字符串的大小,所以用一个指针扫,字符串哈希和二分,判断大小。
同类串排序的方法参照 [SNOI2019]字符串。
The Sum of Good Numbers
我们知道一定有一个数的位数大于等于 \(|m|-1\),所以分三种情况。
-
两个数位数都是 \(|m|-1\),直接扔到 ans 里。
-
前一个是 \(|m|\),可以找前一个与 m 的 lcp,后一个的长度也就确定了。
-
后一个是 \(|m|\) 同理。
拿出 ans 中每个三元组进行 check,可以用哈希,因为是 CF 题,所以七重模数大哈希就行了。
Reverses
把 \(a,b\) 交叉串连得到 \(c\),发现相当于将 \(c\) 划分为偶数回文串的最小贡献。
建出 PAM,回文串长度为 \(2\) 的时候特判,对于每个等差链上维护最佳转移点,转移时暴力跳链,复杂度 \(O(n\log n)\)。
Palindrome Addicts
离线,转换为区间查询本质不同回文串,原题是 Loj6070。
每一个新的回文串会对前面一段区间有贡献,然后发现一条等差链上的串的贡献形成了一段区间,需要用线段树找左端点,发复杂度 \(O(n\log^2 n)\)。
原题因为强制在线,所以用的是主席树,这里可以改为树状数组,但是发现查询的左端点单调向右,所以可以换一个指针扫。
虽然仍是 \(O(n\log^2 n)\),但是现在能过了。
Boboniu and Banknote Collection
每次遇到一个 \(A\overline{A}A\) 就合并成一个 \(A\) 一定不劣,于是最后剩下一个不含有 \(A\overline{A}A\) 的串,预处理折前缀能折多少次,然后暴力折后缀,复杂度 \(O(n\log n+n\sqrt n)\)。
本文来自博客园,作者:mikefeng,转载请注明原文链接:https://www.cnblogs.com/mikefeng/p/17475472.html

浙公网安备 33010602011771号