昨天晚上打 CF 去了,没写日记。
CF1400 的题都做不对的 OIer 有什么用?
Wonderful Lightbulbs↗
我们有结论:设最初的灯泡在 ,那么第 行一定有奇数个灯泡在亮,它所在的对角线也一定有奇数个灯泡在亮。
Wonderful Teddy Bears↗
首先我们把字符映射一下:。考虑 种操作:
让我们从逆序对的角度考虑:对于第 种操作,只会减少 个逆序对,对于第 个操作,会减少 个逆序对。显然我们应该贪心的先做 操作直到做不动为止。
我们看何时 操作做不动了。当且仅当 变成形如 ,也就是说, 可以被分成一个全为 的前缀和一个全为 的后缀,和一个 交替出现的字串。
因为 交替出现,我们考虑记录 表示总的 的个数, 表示在偶数位置上的 的个数。依然考虑这 种操作: 操作不会改变 , 操作会使 变化(增加或减少)。考虑 的最终形态是什么。因为 会全聚在 的前面,所以 的目标是 。于是我们可以这样:设总共有 逆序对,先做 次 操作。 减少 ,然后再做 次 操作。
Unpleasant Strings↗
看到 ,看能不能搞出一种 的算法。
我们想到预处理 串上每个下标 的 ,表示以 结尾的子序列最少还要加多少个字符才能不再成为悦耳字符串。
考虑如何预处理。 从后往前枚举,记录一个 表示字符 最后出现的地方。我们枚举每个字符。有显然的转移:,表示在这个点后面接每个字符的方案。 初始全为 ,且 。再记录一个 ,每次都把 给 memcpy 进 。转移完了再更新 。最后把 memcpy 进 。
考虑如何处理询问。就像字典树一样,我们记录一个 表示当前跳到了 这个点。枚举 里每个字符 ,每次跳到 。如果说跳着跳着直接跳到 了,就说明它本就不是悦耳字符串, 置为 并 break。反之如果跳到了 的结尾了都没跳出去,就说明这是一个悦耳字符串,答案即为 。
code:
#include<bits/extc++.h>#define inf 0x3f3f3f3fusing namespace std;const int maxn = 1e6 + 5;int n,k,q;char t[maxn],s[maxn];int son[maxn][26],ans[maxn];signed main(){ scanf("%d%d%s",&n,&k,t + 1); fill(son[0],son[0] + k,n + 1);// 这里直接把 son[0] 当 lst 用了 fill(ans + 1,ans + n + 1,inf);// ans 初始化 inf for (int i = n; i >= 1; i--) { memcpy(son[i],son[0],sizeof(int) * k);// 把 lst memcpy 进 son[i] for (int j = 0; j < k; j++) ans[i] = min(ans[i],ans[son[0][j]] + 1);// 转移 son[0][t[i] - 'a'] = i;// 更新 lst } scanf("%d",&q); while (q--) { scanf("%s",s + 1); int rt = 0,len = strlen(s + 1); for (int i = 1; i <= len && rt <= n; i++) rt = son[rt][s[i] - 'a'];// 每次跳,如果跳出去了就说明本就不是悦耳字符串。 printf("%d\n",ans[rt]); } return 0;}Bermuda Triangle↗
式子推推推推到厌倦
后日谈
去开拓把,即使前方道路未卜。
