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