CF1450G [* hard]
给定字符串 (S),保证不存在 t,r,y,g,u,b
,即字符集 (mathbf{Sigma}) 为 (20)
给定常数 (k=frac{a}{b}),你可以执行以下操作:
- 选择字符 (c),设其出现集合为 ({i_1,i_2...i_m}),则当 (kcdot (i_m-i_1+1)le m) 时,可以将 (c) 改成任意一个当前字符串 (S) 中存在的字符。
假定经过若干次操作,最后可以使得整个串变成一个字符,那么称此字符合法,求所有合法的字符。
(|S|le 5000,ale ble 10^5)
Solution
考虑假设我们执行了操作 (x o y),则连接 (y o x),则最后的图必然是一棵树。
设 (f_{S}) 表示当前得到了点集 (S) 且集合 (S) 能够继续操作,此时 (f_S=1)
我们先预处理点集 (T) 能否操作,设数组为 (g)
考虑我们的操作只有两种:
- 给当前森林增加一个根。
- 用两棵森林拼接得到当前点集。
对于第一类操作,当前仅当点集 (f_{Sland{y}}) 为 true
且 (g_{S}=1) 时其为 true
。
对于第二类操作,转移为枚举子集 (S),当前仅当两者均为 true
时其为 true
。
于是我们得到了一个 (mathcal O(3^{mathbf{|Sigma|}}+n)) 的做法。
接下来有一个很强的性质,考虑第二类转移,设 (mathbf{range(S)}) 表示点集 (S) 的元素构成的区间,则可以发现,对于第二类转移,我们只需要转移 (mathbf{range(S)},mathbf{range(T)}) 不相交的部分。
证明如下:
首先可以假设 (S,T) 对应的状态均为一棵树,那么我们有这样的结论:我们可以通过调整将 ({Scap T}) 这样的一个森林调整为一棵树。
首先因为 (S,T) 满足限制,于是显然有 (g_{Scap T}=1)(考虑到长度更小,元素更多)
于是我们可以将原 (S) 的根拿出来,并考虑将 (T) 接在下来,显然这可以到达且合法。
接下来考虑假设 (S,T) 均为森林,我们考虑若干棵树并在坐标上进行排布,任意一对的相交都可以执行上述性质变成不相交的情况,于是我们只需要依次转移不相交的情况即可得到答案。
于是我们按照左端点排个序,对于第二类转移只需要检查 ({c_1,c_2...c_i}cup S) 即可。
tips:元素 (c) 合法当且仅当 (f_{mathbf{All}land c}) 合法。