Codeforces试题乱做 Part3

啊, 时间过的好快啊, 最近考试好多, 改题让我时间好少, 还是希望能多做点自己想做的题, 那就卷一点吧.

这个 \(\text{Part}\) 怎么也得省选前搞定吧.


\(\text{[CF1097G]Vladislav and a Great Legend}\)

\(\color{blue}{\text{[NORMAL]}}\)

啊, 好的, 我以后知道怎么算 \(\sum\limits_{n}{f(n)^k}\) 这种东西了.

\[x^k = \sum_{i=0}^{k}{\binom{x}{i}\begin{Bmatrix}k \\ i\end{Bmatrix} i!} \]

这个考虑组合意义就行.

其实 \(x^k\) 这种形式不一定只有斯特林数一种思路, 如果只想斯特林数早晚得寄.

推导式子可得,

\[ans=\sum_{i=0}^k{i!\begin{Bmatrix}k\\i\end{Bmatrix}\sum_{S}{\binom{f(S)}{i}}} \]

外面枚举 \(i\) 肯定没毛病, 那就考虑里面那个组合数怎么做, 考虑其组合意义, 对于每一个点集组成的生成树, 在树里面选 \(i\) 条边染色的方案数.

\(f_{x,i}\) 表示 \(x\) 的子树内选出一个有 \(i\) 条边被染色的非空生成树的方案数.

类似树形背包的转移, 但这个树形 \(dp\) 有点细节我觉得, 很容易就会忘记考虑新的子树和父亲的边.

考虑新加入一个子树, 那么:

  1. 只有原来的子树.
  2. 只有新的子树 (加上 \(x\rightarrow y\) 这条边).
  3. 原来的和新的共同组成 (加上 \(x \rightarrow y\) 这条边).

时间复杂度 \(\mathcal{O}(nk)\) .


\(\text{[CF679E]Bear and Bad Powers of 42}\)

\(\color{blue}{\text{[NORMAL]}}\)

因为 \(42\) 的幂次越往大越在值域内的就越少, 线段树维护每个数到 \(42\) 的幂次差多少, 以及区间 \(\min\) , 若当前最小值小于要加的数, 那就递归下去暴力修改.

区间赋值也是好做的, 标记下传的时候注意顺序即可.

定义连续段的势能为值域内大于其值的 \(42\) 的幂的个数, 那么一次操作最多会被递归 \(\log_{42}{nV}\) 次. 单次操作复杂度为 \(\mathcal{O}(\log_{42}{nV}\log{n})\) .

总体复杂度为 \(\mathcal{O}(q\log_{42}{nV}\log{n})\) .


\(\text{[CF889E]Mod Mod Mod}\)

\(\color{red}{\text{[HARD]}}\)

\(g(x,i) = x \bmod a_1 \bmod a_2 \bmod a_3 \dots \bmod a_i\) .

发现, 只要 \(\forall i,g(x,i) \not = 0\) , 则有 \(\forall i,g(x-1,i)=g(x,i)-1\) , 也就只要保证 \(x \bmod a_i\) 都不是 \(0\) , 可以随意降低 \(x\) , 都不影响 \(g(x,i)\) 之间的相对差.

\(f(i,R)=y\) 表示如果 \(x \bmod a_i\) 最后变成了 \(0 \sim R\) , 这时多出来的部分的最大值都可以是 \(y\) .

这时可以设计 \(dp\) , 用 \(map\) 存二元组 \((R,y)\) , 在 \(i\) 处枚举所有二元组试图使其适配 \(a_{i+1}\) .

  • 如果 \(R < a_{i+1}\) , 则二元组不变.
  • 否则可以直接延展到 \(a_{i+1}\) , 变为 \((R \bmod a_{i+1},y')\) .
  • 如果 \(R \geqslant a_{i+1}\) , 可以把 \(R\) 降低到 \(a_{i+1}-1\) , 使得 \(i+1\) 成为卡着上界的地方, 变为 \((a_{i+1}-1,y'')\) .

除了以上转移方案, 其他方式都不能保证 \(R\) 存在一个位置卡满上界.

一共只会产生 \(n\) 个新的 \(R\) , 故复杂度为 \(\mathcal{O}(n\log{a_i}\log{n})\) .


\(\text{[CF571D]Campus}\)

\(\color{blue}{\text{[NORMAL]}}\)

感觉这种集合合并的东西总能并查集离线做, 下次要牢记这种套路.

合并时新建一个虚电, 先把森林建出来, 问题就转化为两个森林分别子树加, 子树赋值.

注意到我们对于每个点只用关注它查询之前最后一次赋值为 \(0\) 的时间以及之后的子树加, 询问就变成了区间求和, 树状数组维护即可.

时间复杂度 \(\mathcal{O}(n+m\log{n})\) .


\(\text{[CF1332G]No Monotone Triples}\)

\(\color{red}{\text{[HARD]}}\)

这题首先要看出 \(b\) 不会太长, 不能超过 \(4\) .

证明大概是分类讨论, 用 \(Dilworth\) 定理证明.

我们可以预处理出 \(1 \sim n\) 中的每个 \(i\) 作为 \(b_1\) 时, 最近的 \(b_3\)\(b_4\) 在哪.

这样对于每组询问只需要 \(ST\) 表维护一下 \([l,r]\) 中最小值和最小位置, 判断一下最小位置是否在 \(\leqslant r\) 即可.

分类讨论 \(3,4\) ,

存在一个长度为 \(3\)\(b\) , 只需要序列 \(a\)\([l,r]\) 中不单调.

对于每一个 \(i\) , 处理出在它前面第一个不同于 \(a_i\) 的位置 \(pre_i\) , 和后一个不同于 \(a_i\) 的位置 \(nxt_i\) , 如果有 \((a_i-a_{pre_i})(a_{nxt_i}-a_i) < 0\) , 则存在一个长度为 \(3\)\(b\{a_{pre_i},a_i,a_{nxt_i}\}\) .

\(b_1=pre_i\) 上记录一个可能的 \(b_3=nxt_i\) , \(ST\) 表维护即可.

存在一个长度为 \(4\)\(b\) , 需要满足 \(b_1,b_4\) 既不是 \(b\) 中的最大值, 也不是最小值.

从前往后维护一个单调不降的单调栈 \(stk_1\) 和一个单调不升的单调栈 \(stk_2\) .

为了使 \(b_1,b_4\) 不成为 \(b\) 中最大或最小值, 不难推出 \(b_4\) 需满足两个条件,

  1. \(b_4\) 既不在 \(stk_1\) 中, 也不在 \(stk_2\) 中.
  2. \(b_4\) 之前存在一个 \(x\)\(stk_1\) 中, 且满足 \(a_x \not= a_{b_4},x > b_1\) , 存在 一个 \(y\) 满足 \(a_y \not= a_{b_4},y > b_1\) .

也就是找到 \(stk_1\) 中第一个严格大于 \(a_{b_4}\) 的位置 \(gt\)\(stk_2\) 中第一个严格小于 \(a_{b_4}\) 的位置 \(lt\) , 然后在 \((\max\{gt,lt\},n]\) 中找到即不在 \(stk_1\) 中也不在 \(stk_2\) 中的最小位置, 这就是符合条件的最小 \(b_4\) , 可以用 \(set\) 维护.

时间复杂度 \(\mathcal{O}(n\log{n}+q)\) .


\(\text{[CF453E]Little Pony and Lord Tirek}\)

\(\color{green}{\text{[EASY]}}\)

考虑到如果一个位置曾变为 \(0\) 那它的贡献是好算的, 如果一段全是 \(0\) , 那这一段的贡献都是好算的.

这让我们联想到分块.

预处理出每个块 \(i\)\(0\) 开始 \(j\) 个单位时间后的和, 我们称一个块是未被限制的当且仅当它在某一时刻被清零, 且未被单点修改过, 这些块可以预处理出答案直接计算贡献, 否则一个块称为被限制的, 暴力计算贡献.

一开始所有块都是被限制的, 每次修改至多将两个块变成限制的, 所以复杂度均摊下来并没有问题.

预处理是采用两次前缀和, 时间复杂度 \(\mathcal{O}(\frac{n^2}{B})\) , 其中 \(B\) 为块长, 块长需自己调整, 以卡空间, 当然也可以通过技巧做到线性.


\(\text{[CF643G]Choosing Ads}\)

\(\color{blue}{\text{[NORMAL]}}\)

摩尔投票法, 受教了.

傻子也看的出答案不能超过 \(5\) 个.

首先考虑 \(p\geqslant 51\) 的情况, 也就是要求区间绝对众数, 摩尔投票法是这样的, 维护当前众数和它的血量 \(HP\) , 每次新加入一个数, 如果它和现在的众数相等, 那么 \(HP+1\) , 否则 \(HP-1\) , 如果 \(HP\) 变为 \(0\) 了, 那么它就寄了, 用杀掉它的数来当新的众数, 其 \(HP\) 变为 \(1\) , 最后剩下的数就是可能的答案.

正确性也比较显然, 如果一个数超过了一半也不可能被别的数干寄.

然后推广到 \(p=20\) 的情况, 维护当前 \(5\) 个众数和 \(HP\) , 合并两个区间就拿两个区间的 \(10\) 个众数暴力合并就行了.

线段树维护即可, 时间复杂度 \(\mathcal{O}(nk^2\log{n})\) , 其中 \(k=\lfloor \frac{100}{p} \rfloor\) .


\(\text{[CF830D]Singer House}\)

\(\color{blue}{\text{[NORMAL]}}\)

一开始就想歪了, 想的是从每个点开始有多少路径可以走, 根本不会做.

\(f_{i,j}\) 为高度为 \(i\) 的二叉树中选出 \(j\) 条不相交路径的方案数.

每次合并的时候考虑把两个高度为 \(i-1\) 的二叉树合并.

然后考虑大概会有四种情况:

  • 不新增任何路径.
  • 新增根结点这一个路径.
  • 将根结点和某一个路径合并.
  • 将根结点和两条路径合并.

时间复杂度 \(\mathcal{O}(n^3)\) .


\(\text{[CF1383E]Strange Operation}\)

\(\color{blue}{\text{[NORMAL]}}\)

考虑操作本质, 11 是删去一个 \(1\) , 否则是删去一个 \(0\) .

考虑一个双射, 一个新序列, 序列中的数表示相邻 \(1\) 之间 \(0\) 的个数, 如 \(s = 0001100101\) , 那么 \(a=\{3,0,2,1,0\}\) , 不难发现每个这样的序列对应一个 01 序列.

最两边的 \(1\) 一定是最后删去的, 对答案的贡献系数为 \((a_1+1)(a_k+1)\) .

考虑一个序列 \(b\) 能被最初始对应的序列 \(a\) 生成, 其充要条件为存在 \(1 \leqslant i_1 < \cdots < i_{|b|} \leqslant |a|\) , 使得 \(b_j \leqslant a_{i_j}\) .

那么判定是否可以生成就是一个很显然的贪心了.

考虑一个 \(f_i\) 可以贡献给哪些 \(i < j\) , 不难发现, 当 \(b\) 值小于等于 \(a_{i+1} \sim a_{j-1}\) , 那么贡献系数为 \(\max\{0,a_j-\max\limits_{k=i+1}^{j-1}\{a_k\}\}\) .

这样就好考虑了, 直接换成有哪些 \(i\) 收到哪些 \(j\) 的贡献, 不难发现单调栈维护即可, 时间复杂度 \(\mathcal{O}(n)\) .


\(\text{[CF1528E]Mashtali and Hagh Trees}\)

\(\color{green}{\text{[EASY]}}\)

嗯, 有的时候你计数题不对, 不一定是 \(dp\) 错了, 可能是你少考虑了啥情况.

\(3\) 个条件不就是有向树的意思嘛 ( \(flag1\) ) , 那剩下两个条件一个是最大深度, 一个是二叉树但根可以有三个儿子的意思嘛.

那不是直接 \(dp\) , 设 \(f_i\) 表示深度为 \(i\) (根的深度为 \(0\) ) 时候的方案数, 转移就考虑有一个儿子或者两个.

\(f_i = f_{i-1}+\dbinom{sum_{i-1}+1}{2}-\dbinom{sum_{i-2}+1}{2}\) , \(sum\)\(f\) 的前缀和, 组合数相减是考虑容斥, 所有的方案数减去全都不的方案数, 然后插板法.

最后答案就是加上第三个儿子的方案数, \(f_n+\dbinom{sum_{n-1}+2}{3}-\dbinom{sum_{n-2}+2}{3}\) .

然后你就发现你过不了样例, 还拍不了, 然后我就笃定, 我一定是转移错了 ( \(flag2\) ) , 捣鼓了 \(20min\) , 决定上票, 然后发现, 少考虑了情况.

还有一种情况是, 一个外向树和一个内向树, 他们之间的根用一条链连起来.

\(g_i\) 为强制根有两个儿子时, 深度为 \(i\) 时候的方案数, 转移类似, 那么答案就应该加上 \(\sum\limits_{i=1}^{n-2}{\sum\limits_{j=1}^{n-i+1}g_ig_{n-i-j}}\) .

容易前缀和优化做到线性复杂度.


又完结一个 \(\text{Part}\) , 发现其实我的套路, 以及各类型的题目都不熟, 很慌, 特别是网络流题, 我永远看不出来是网络流, 得好好加油了啊.

posted @ 2022-09-26 21:03  Lonely923  阅读(30)  评论(0编辑  收藏  举报