CF 2100-2400 strings 乱做

CF1995D Cases

显然如果选了某个字符那么不妨选它出现的所有位置。check 方式等价于相邻两个选择的位置间距 \(\le k\),等价于连续 \(k\) 个必须选一个(最后一个必须选)

枚举位置维护字符集是做不了的,状态数 \(O(n2^c)\) 无法优化

考虑枚举字符集 \(s\)。设原串连续 \(k\) 个字符的字符集为 \(t_i\),合法的 \(s\) 满足 \(s\cap t_i\ne\varnothing\)。标记 \(U\setminus t_i\) 及其子集,没有标记即为合法

时间复杂度 \(O(cn+2^cc)\)

CF1980G Yasya and the Mysterious Tree

\(dis[u]\) 为根链边权异或

按套路用 trie 维护 \(dis\) 即可查询。注意查询前需要先删除自己
所有边异或 \(x\) 等价于给 \(dep\) 为奇数的 \(dis\) 异或 \(x\),奇偶分别维护即可

CF1970D1 Arithmancy (Easy)

长度限制 \(30n\),可以令长度分别 \(\approx1,30,90\),这样用本质不同子串数的大小就可以确定是哪两个串,只需要判断顺序

\(n=2\) 时容易构造出 OX O...O。顺着往下想,\(n=3\) 时可以增加一个前缀 O、后缀 X、中间随机的串

官方题解说直接随就行。。。

CF1968G2 Division + LCP (hard version)

注意到 \(lcp\) 一定是原串前缀,从小到大枚举长度 \(i\)\(s[1:i]\) 下一次出现的位置为 \(\min\{j:j\ge p\land z[j]\ge i\}\),并查集维护 \(z[]\ge i\) 的位置。只会查找 \(O(n\ln n)\)

官方题解是基于 \(lcp\cdot k\le n\) 的根号分治

CF1965C Folding Strip

注意到只要求所有折叠后对应位置相同,所以应该关注结果而不是过程

显然长度 \(>2\) 的连续段等价于长度 \(=1,2\) 的。感性理解:要让最终的长度尽量小就要让折叠次数尽量多,事实上可以再每个 \(=2\) 的连续段中间折一次,这样最终的串的 \(0/1\) 分别在奇/偶位置

实现

从左到右模拟折叠。维护方向 \(d\),相对位置 \(j\)

int l = 0, r = 0;
	For(i,2,n, d = 1, j = 0) {
	if( s[i-1] == s[i] ) d *= -1;
	else j += d;
	ckmin(l, j), ckmax(r, j);
	}
	cout<<r-l+1<<'\n';

CF1930D2 Sum over all Substrings (Hard Version)

反过来考虑,\(q_i=1\) 可以覆盖 \(p_{i-1},p_i,p_{i+1}\),可以从前往后贪心

sol 1

\(f[i,j]\) 表示覆盖了 \([l,i]\),最后一个 \(1\) 位于 \(i-j\) 的最小代价(\(j\in\{0,1,2,\ge3\}\)

矩乘

sol 2

\(f[l,i]\) 表示覆盖了 \([l,i]\) 的最小代价

\[f[l,i]=\begin{cases} f[l,i-3]+1 & ,p[i]=1 \\ f[l,i-1] & ,p[i]=0 \end{cases} \]

把右端点相同的合并计算,设 \(g[i]=\sum_{l\le i}f[l,i]\)

\[g[i]=\begin{cases} g[i-3]+i & ,p[i]=1 \\ g[i-1] & ,p[i]=0 \end{cases} \]

posted @ 2024-09-02 20:58  ft61  阅读(27)  评论(0)    收藏  举报