
日记
昨天晚上打 CF 去了,没写日记。
CF1400 的题都做不对的 OIer 有什么用?
Wonderful LightbulbsLink to
我们有结论:设最初的灯泡在 ,那么第 行一定有奇数个灯泡在亮,它所在的对角线也一定有奇数个灯泡在亮。
Wonderful Teddy BearsLink to
首先我们把字符映射一下:。考虑 种操作:
让我们从逆序对的角度考虑:对于第 种操作,只会减少 个逆序对,对于第 个操作,会减少 个逆序对。显然我们应该贪心的先做 操作直到做不动为止。
我们看何时 操作做不动了。当且仅当 变成形如 ,也就是说, 可以被分成一个全为 的前缀和一个全为 的后缀,和一个 交替出现的字串。
因为 交替出现,我们考虑记录 表示总的 的个数, 表示在偶数位置上的 的个数。依然考虑这 种操作: 操作不会改变 , 操作会使 变化(增加或减少)。考虑 的最终形态是什么。因为 会全聚在 的前面,所以 的目标是 。于是我们可以这样:设总共有 逆序对,先做 次 操作。 减少 ,然后再做 次 操作。
Unpleasant StringsLink to
看到 ,看能不能搞出一种 的算法。
我们想到预处理 串上每个下标 的 ,表示以 结尾的子序列最少还要加多少个字符才能不再成为悦耳字符串。
考虑如何预处理。 从后往前枚举,记录一个 表示字符 最后出现的地方。我们枚举每个字符。有显然的转移:,表示在这个点后面接每个字符的方案。 初始全为 ,且 。再记录一个 ,每次都把 给 memcpy
进 。转移完了再更新 。最后把 memcpy
进 。
考虑如何处理询问。就像字典树一样,我们记录一个 表示当前跳到了 这个点。枚举 里每个字符 ,每次跳到 。如果说跳着跳着直接跳到 了,就说明它本就不是悦耳字符串, 置为 并 break
。反之如果跳到了 的结尾了都没跳出去,就说明这是一个悦耳字符串,答案即为 。
code:
123456789101112131415161718192021222324252627282930
#include<bits/extc++.h>
#define inf 0x3f3f3f3f
using 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 TriangleLink to
式子推推推推到厌倦
后日谈 Link to 后日谈
去开拓把,即使前方道路未卜。
日记
© 伊埃斯 | CC BY-NC-SA 4.0