Deltix Round, Autumn 2021
E
https://codeforces.com/contest/1609/problem/E
给你字符串只包含abc
给你q次操作,每次操作修改一个位置上的字符为’a’/‘b’/‘c’中的一种
每次操作后,问对于当前字符串,至少修改多少个字符,使字符串不包含abc子序列
子序列定义: 字符串任意位置删除任意个得到的剩余字符串
范围
字符串长度 1e5
询问次数 1e5
题解
一个可以过的方案是
seg(l,r,state) = 最少次数
其中l,r
表示一个区间,通过线段树维护
state 是 5bit的状态分别对应a,b,c,ab,bc, 是否在区间中出现过
那么 线段树节点关系 是
f(根, mergestate(statel,stater)) = min(f(左节点,statel)+f(右节点,stater))
其中 产生abc
的不更新 根节点状态
问题是 实现起来感觉有点卡常数 $q \cdot log(N) 32 \cdot 32 $ 的运算量 ,2464ms/3000ms 过的, 看到有些其它状态设计,状态如果更少会更快
tourist 300ms 过的
另一个想法是,实际上变成 [不存在a][不存在b][不存在c]
的字符串就好了
那 操作代价(其实就是分别移除a,b,c) = count[a][0..i]+count[b][i+1..j]+count[c][j+1..end]
所以对count计算总是先a后b再c
变成了维护 f(l,r,startch, endch) = 最少代价
也就是 在区间[l,r]上 起始位置是计算startch,结束位置是计算endch
这样状态数最多3x3
,根据a,b,c
的顺序, 真实有效的只有6 个, 计算代价 常数就小很多
代码(前一种)
https://codeforces.com/contest/1609/submission/137409899
1 |
|
可能包含改成恰好包含快了不少
https://codeforces.com/contest/1609/submission/137444815
1216 ms/3000 ms
1 |
|