Loading

脱离昨日的夏日烟火落下时溅起回忆中的深夜雨

CF1852E Rivalries

首先,我们只关心每种数 \(x\) 出现的第一个位置和最后一个位置 \(l_x,r_x\)

此时,若有两个数 \(x<y\),满足 \(l_x<l_y\leq r_y<r_x\),那么 \(x\) 就一点用没有,去除掉这些 \(x\) 之后,剩下的每种数一定至少在端点处是有用的,我们先把这些位置填了。

此时,对于有用的数 \(x\),其只能在 \([l_x,r_x]\) 内填数。

此时对于剩下的位置,一个显然的想法是,位置 \(i\) 填上所有 \(i\in [l_x,r_x]\)\(x\) 最大值,记为 \(b_i\)

但是事实上,我们还可以填一些没有用的数,但是要满足他们不影响现在的权重。

注意到若填了两种及以上不同的没用的数,我们不妨换成最大的一个,这样不仅和变大了,而且其也更不容易被计算到权重里,因此最多有一种没用的数,设为 \(c\)

那么,一定存在一种有用的数 \(x\),满足 \(c<x\)\(l_c<l_x\leq r_x<r_c\),我们不妨枚举 \(x\)

此时贪心地,\(c\) 一定是填小于 \(x\) 的最大的 \(c\) 最好,我们先把 \(b_i>c\) 的先填上 \(b_i\) ,剩下的位置填上 \(c\) 。但是这样不一定合法 ,因为我们要保证 \(l_x,r_x\) 两侧各有至少一个 \(c\) ,如果已经有了就不用管了,否则选择 \(b\) 最小的一个换成 \(c\) 即可。

实现不是难点。

CF1835E Old Mobile

首先,因为我们可以记住按过的键,所以串里的字符只有第一次出现是有用的,所以我们去重之后求出 额外按键次数,然后加 \(n\) 就好了,去重之后字符之间没有区别,我们记作 \(1\to k\)

我们把 \([1,k]\) 的字符称为 有用字符\([k+1,m]\) 的字符称为无用字符。

考虑我们的策略是什么:

很明显这个删除键非常重要,因此我们分是否知道删除键的位置讨论:

知道删除键的位置

\(f_{i,j}\) 表示已经按出了 \(i\) 种无用字符, \(j\) 种有用字符的概率,\(F_{i,j}\) 为其期望次数。

  • 串中下一个字符我们已知,此时不需要额外按键次数,不转移
  • 串中下一个字符未知,那么我们就需要随机按一个
    • 按中一个无用的字符 需要先删掉,然后转移到 \(f_{i+1,j}\),花费的次数是 \(2\)
    • 按中一个有用的字符,但是不是串中下一个 需要先删掉,然后转移到 \(f_{i,j+1}\) 花费次数是 \(2\)
    • 按中一个有用的字符,且是串中下一个 不需要删掉,转移到 \(f_{i,j+1}\),花费次数 \(0\)

概率都是很好算的。

不知道删除键的位置

那么我们可能会打出一个不符合原串的后缀,并且一旦打出来第一个不符合原串的字符,我们接下来唯一的目的就是寻找删除键,然后把这些不符和的都删除。

\(g_{i,j}\) 表示已经按出了 \(i\) 种无用字符,\(j\) 种有用字符,且当前打出的字符完全符合原串的概率,\(G_{i,j}\) 为其期望。

\(h_{i,j}\) 表示已经按出了 \(i\) 种无用字符,\(j\) 种有用字符,且当前打出的字符至少有一个不符合原串的概率,\(H_{i,j}\) 为其期望。

\(g:\)

  • 串中下一个字符我们已知,此时不需要额外按键次数
  • 串中下一个字符未知,此时需要随机按一个
    • 按中删除键 转移到 \(f_{i,j}\),需要 \(2\) 的额外花费,因为需要把不小心删的打回来
    • 按中无用字符/有用但不对的字符 转移到 \(h\) 并且我们迟早会删掉这个字符,所以一定有 \(2\) 的代价
    • 按中有用且对的字符 转移到 \(g\),无额外代价。

\(h:\)

  • 串中下一个字符我们已知,此时不需要额外按键次数
  • 串中下一个字符未知,此时需要随机按一个
    • 按中删除键 转移到 \(f_{i,j}\) 并且误删的那个代价算过了,所以代价为 \(0\)
    • 按中别的字符 转移到 \(h\) 并且我们迟早会删掉这个字符,所以一定有 \(2\) 的代价

特殊注意一下\(i=j=0\) 时删除键不需要补代价。

最终的贡献,我们很明显一旦知道了其他 \(m\) 个键剩下的是什么也很清楚了,因此有不止一种合法终态。

[CCPC 2023 北京市赛] 三染色

\(\bmod 3\) 意义下不太好考虑,我们先考虑普通情况:

  • 有一个高度矩阵 \(h_{i,j}\),满足相邻的 \(h\) 差的绝对值不超过 \(1\),然后对于每一轮,如果某个点周围存在点的高度是 \(h_{i,j}-1\),那么 \(h_{i,j}=h_{i,j}-1\),否则不变,最终停止变化的时刻。

这个问题是简单的,因为最小值一定不变,并且每一轮最小值都会把周围的点更新为最小值,因此答案就是到 \((1,1)\) 曼哈顿距离最小的最小值点的距离。

考虑拓展一下,我们构造一个高度矩阵 \(h_{i,j}\),使得除了满足上述条件,并且 \(h_{i,j}\equiv a_{i,j}\pmod 3\),可以发现若能构造出来,那么 \(h\)\(a\) 的变化就一模一样的,答案就是上面的东西。

不妨令 \(h_{1,1}=a_{1,1}\),然后归纳假设已经构造了 \(h_{i-1,j},h_{i,j-1}\),因为 \(|h_{i-1,j-1}-h_{i-1,j}|\leq 1,|h_{i-1,j-1}-h_{i,j-1}|\leq 1\) 都满足,所以通过简单的分类讨论可以发现当且仅当这个子矩阵形如这样时无法构造:

\[\begin{pmatrix} a & a\\ b & c \end{pmatrix} \]

当然,旋转或者整体加 \(d\) 都也是不行的。

手玩一下可以发现,此时这个矩阵会不断自我迭代,因此一定不会停止。故只要不存在这样的子矩形就一定是可以构造的,这就是第一问的答案,直接 \(3^{2n}m\) 暴力状压 dp 即可通过。

对于第二问,我们需要维护最小高度,当前的高度,最小值位置,以及最后一列的状态,显然过不掉,考虑优化。

首先可以用轮廓线 dp 把状态变成 \(3^n\),然后注意到我们不关心最小值具体是什么,只关心当前高度与最小高度的差,具体的,我们可以一开始就枚举 \(h_{1,1}\) 比最小值高多少,并且实时记录差,强制过程中不经过差 \(<0\) 的点,那么差 \(=0\) 的点就是最小值点。

同时,我们其实也不关心最小值位置,只关心其曼哈顿距离,可以发现曼哈顿距离相等的点构成了一条斜线,我们只需要记录这一条线与当前列的交点即可,这个交点如果超出边界,以后也不可能更新了,直接计入答案即可,否则这个交点是 \(O(n)\) 的。

综上,我们能在 \(O(3^nn^2m^2)\) 的复杂度解决该问题。

CF1887F Minimum Segments

首先我们给出颜色数 \(col\) 的上下界:

  • 上界:\(r_i\neq n+1\)\(r_i-i+1\) 的最小值,这很显然。
  • 下界:把 \(r_i\) 集合内的点称为关键点,下界为 \([i+1,r_i]\) 内关键点个数的最大值 \(+1\),这也很好理解。

结论:若 \(col\) 在上下界之间,一定有解,下面给出构造:

首先有显然的性质:若 \(r_i\neq r_{i+1}\),则 \(a_i\) 下一次出现的位置为 \(r_{i+1}\)

考虑从 \(i\)\(a_i\) 上一次出现的位置连边(不存在就是 \(0\) )。

我们从左到右依次遍历每个 \(i\),若 \(i\) 没有向前连边,就找到最靠左的一个没有被后面连边的点,连过去( \(0\) 可以被连 \(col\) 次),最后剩下的点从 \(n+1\) 连过去。

正确性:

因为满足上界,所以对于 \([i,r_i]\),一定不会存在 \(j<i\),使得 \(nxt_j>r_i\),这样的话,跨过 \(i\) 的边的个数就是 \([i,r_i]\) 内的颜色个数,可以归纳证明出都是 \(col\) 。 设 \(s_i\) 表示前 \(i\) 个位置向后有边的点个数,\(d_i\) 表示向后连的位置 \(> i\) 的点的个数,那么前 \(i\) 个位置需要向左连边的个数为 \(i-(s_i-d_i)\),可以向右连边的个数为 \(col+i-s_i\),那么若 \(i-(s_i-d_i)\leq col+i-s_i\) 恒成立,根据 Hall 定理一定合法,可以发现满足下界时一定合法,并且这样连一定是最小的。

注意特判一些明显无解的情况即可,复杂度 \(O(n)\)

[Atcoder World Tour Finals 2022 Day1 C] Shrink the Tree

首先把树黑白染色,那么两个距离为奇数的而节点的颜色一定不同。

我们考虑一棵子树 \(t\),考虑一下删除它的情形,我们先要求根是最后删的,设 \(W(t),B(t)\) 为子树内的白色,黑色节点个数,不妨假设 \(W(t)> B(t)\) ,那么我们删除的过程形如:

  • 先删除若干异色叶子,直到删不了
  • 此时所有叶子同色,并且因为删除是成对的,现在依旧满足 \(W'(t)> B'(t)\) ,并且一定所有叶子都是白色,因为如果都是黑色,那么每个白色节点都能匹配至少一个黑色儿子,与个数关系矛盾。那么此时我们必须要从子树外面借来一个黑色节点消掉一个白色叶子,然后不断重复这两步操作直到 \(W'(t)=B'(t)\) ,容易发现这过程中恰好从外面借来了 \(W(t)-B(t)\) 个黑色节点。

此时满足 \(W(t)=B(t)\),我们还是能删就删,类似上面的分析可以发现,当删不了的时候,这个子树剩下的是一条从根向下的链需要借外面的点,我们贪心地想要最小化这个链的长度。设这时候,总共需要从外面借的点的个数为 \(best(t)\)

假设我们已经会求了,那么我们最终一定删除了若干个子树 \(t_1,t_2……t_k\),那么我们给出这些子树能被删除的充要条件:

  • \(\sum_{i}W(t_i)=\sum_iB(t_i)\)
  • 这些子树的根节点颜色不能全相同
  • \(\forall i,best(t_i)\leq \sum_{j\neq i}s(t_j)\),其中 \(s(t_i)\) 为树 \(t_i\) 的节点个数。

这个条件显然是必要的,事实上也是充分的:

我们任选一棵子树 \(t_i\),若其 \(W(t_i)>B(t_i)\),那么一定能找到另一棵树 \(t_j\),满足 \(W(t_j)<B(t_j)\),这两个就可以互相消掉。可以发现消完之后就剩下了一堆链,那么满足前两个条件就一定是有解的。

有了充要条件之后,我们也可以求出 \(best(t_i)\) 了:

  • 自底向上求出 \(best(t_i)\),那么合并 \(t_i\) 的儿子就是等价于找到最小的个数 \(c\),使得存在一种加入 \(c\) 的单点的方案,使得这些单点以及儿子子树可以消掉,利用上面的充要条件可以简单求出来。

然后考虑计数,三个条件的前两个只需要记录黑色节点和白色节点个数、根是否颜色相同就行了,第三个条件等价于 \(best(t_i)+s(t_i)\leq \sum s\),我们只需要枚举 \(\sum s\),就可以判断每个子树是否能被加入了,然后在树上跑个暴力 dp ,复杂度 \(O(n^5)\),求答案的时候枚举没删除的节点中深度最浅的一个,那么这个子树的子树补也是要被删除的。

需要特判一下整棵树能被删空的情况,充要条件是黑白节点个数相等。

[Atcoder World Tour Finals 2022 Day2 D] Cat Jumps

好牛的题啊。

首先,题目求的是恰好 \(k\) 个和为 \(0\) 的部分,我们二项式反演一下变成钦定若干个部分和是 \(0\)

题目中的每种 \(A_i\) 是相同的,我们先当成不同的算,然后除掉每种内部的方案数。

对于每一部分,假设其中的数是 \(A_1,A_2\cdots A_k\),那么就有 \(S=\sum A_k\)\(-1\),之后加入第 \(i\)\(A\) 的方案数就是 \((S+i)\) ,也就是总方案数是 \(\prod\limits_{i=1}^k(S+i)\)

考虑这个东西的组合意义:我们从每个 \(A_i\) 从其同一部分选一个 \(A_j\), 连一条边权为 \(A_j+[j\leq i]\) 的边,所有方案下的边权的乘积的和,容易发现这样和上面是等价的。

这样之后最终连边的形态是一片基环树森林,我们假设求出 \(g_k\) 表示恰好 \(k\) 个连通块的权值和,那么原问题就是把这些连通块分成若干部分,也就是乘上第二类斯特林数。

\(g_k\) 还是不好求,我们再做一步二项式反演,钦定若干个环,没有被钦定的点乱连,这些点的权值显然是 \(\sum_j A_j+i\),我们重点考虑一下环上的方案。

环上 \(i\to j\) 的边的权值是 \(A_j+[j\leq i]=(A_j+1)-(j>i)\),然后相乘。考虑其组合意义:选取一部分点取到 \((A_j+1)\),一部分满足 \((j>i)\) 的点取到 \(-1\),然后相乘,换句话说,就是从环上选取若干条链,满足每条链元素单调,然后链首的贡献是 \((A_j+1)\),剩余点贡献 \(-1\),所有选法的总和。

我们设 \(dp_{i,j}\) 表示考虑前 \(i\) 个点,有 \(j\) 个这样的链的权值和,那么最终只需要把这些链拼成环,也就是乘上第一类斯特林数就行了。

最后,我们有 \(dp_{i,j}=dp_{i-1,j-1}(a_i+1)+dp_{i-1,j}(\sum A+i+(-1)\times j)\),分别代表选为链首、环外、链中间的权值。

复杂度 \(O(n^2)\)

P10255 一首诗

差分一下,维护每种长度的连续段的出现次数,那么问题变成:前缀加一个以一结尾的、公差为一的等差数列,查询全局异或和。

一般情况应该是做不了的,但这个修改有一个隐藏的性质:所有本质不同的连续段长度最多有 \(O(\sqrt n)\) 中,也就是自然根号,这样就可以把序列划分成 \(O(\sqrt n)\) 个等差数列,对于每个等差数列:

  • 若公差 \(d\leq \sqrt n\),我们可以预处理前缀异或和
  • 若公差 \(d>\sqrt n\),此时总共最多只有 \(O(\sqrt n)\) 个位置需要查询,暴力即可。

总复杂度 \(O(n\sqrt n)\)

posted @ 2024-04-04 21:51  Larunatrecy  阅读(33)  评论(0编辑  收藏  举报