Codeforces试题乱做 Part6
这个暑假, 必须疯卷!
\(\text{[GYM102759E]Chemistry}\)
\(\color{green}{\text{[EASY]}}\)
知道耳分解就好做, 不知道就不好做.
考虑模拟耳分解的过程, 设 \(f_S\) 表示集合 \(S\) 强连通的最小代价, \(g_{S,i,j,0/1}\) 表示正在构造耳 \(i\) 到 \(j\) 不能/能走 \((i,j)\) 这条边.
貌似第三维并不用.
转移很简单, 时间复杂度 \(\mathcal{O}(2^nn^3)\) .
\(\text{[CF1305G]Kuroni and Antihype}\)
\(\color{blue}{\text{[NORMAL]}}\)
增加一个点 \(n+1\) , 其权值为 \(0\) , 这样所有操作做完之后, \(2\) 操作会形成一棵树, 如果将边权定为 \(a_i+a_j\) , 那么答案就会是边权之和减去点权之和, 于是问题变成了最大生成树.
考虑 \(Boruvka\) 算法, 高维前缀和求出集合 \(S\) 的子集中的最大点权, 以及另一个连通块的最大值, 即记录最大值和次大值, 且满足两个不在同一连通块.
时间复杂度 \(\mathcal{O}(18\times 2^{18}\log{n})\) .
\(\text{[CF1446D2]Frequency Problem (Hard Version)}\)
\(\color{green}{\text{[EASY]}}\)
首先找到全局众数 \(m\) , 不难发现 \(m\) 一定是两个众数中的一个, 对于一个 \(x(x\not =m)\) , 设 \(x\) 的全局出现次数为 \(cnt_x\) , 若我们能用 \(\mathcal{O}(cnt_x\log{n})\) , 就成功了.
我们将 \(x\) 的位置从小到大排序, 维护 \(m\) 的出现位置集合 \(S\) , 按顺序枚举 \(x\) 的所有出现位置 \(pos_i\) , 并将 \(S\) 中第一个大于 \(pos_i\) 的元素标记, 并删除. 然后我们反过来做一遍同样的事.
这样每个 \(x\) 都标记了不超过 \(2\) 个数, 总数为 \(\mathcal{O}(cnt_x)\) 的, 对于那些没有标记到的点, 我们一定不能让它出现在答案区间中. 所以让它们充当分隔符, 计算区间内答案即可.
时间复杂度 \(\mathcal{O}(n\log{n})\) .
\(\text{[CF150E]Freezing with Style}\)
\(\color{green}{\text{[EASY]}}\)
路径中位数很容易想到二分答案, 变为判断有没有一条路径权值大于等于 \(0\) .
考虑点分治, 不难想到按 \(dep\) 排序后树状数组维护, 加二分的 \(\mathcal{O}(n\log^2{n}\log{w})\) 做法.
开两个数组 \(f\) 表示之前所有子树中深度为 \(i\) 的最大值, \(g\) 表示当前.
要判断的就是 \(\max\{f_i+g_j|L\leqslant i+j \leqslant R\} \geqslant 0\) .
发现随着 \(j\) 递减, 可选的 \(i\) 区间固定向右滑动, 可以按子树最大深度排序后单调队列求解.
时间复杂度 \(\mathcal{O}(n\log{n}\log{w})\) .
\(\text{[CF765F]Souvenirs}\)
\(\color{green}{\text{[EASY]}}\)
把询问挂在右端点, 相当于往前跳, 查询第一个值大于 \(a_i\) 的.
由 \(a_{j'}-a_i < a_j-a_{j'}\) , 移项 \(a_{j'}-a_{i} < \frac{1}{2}(a_j-a_i)\) , 发现每次减半, 往前跳的个数是 \(\log{V}\) 的, 树状数组维护后缀最小值即可.
时间复杂度 \(\mathcal{O}(n\log^2{V})\) .
\(\text{[CF436F]Banners}\)
\(\color{green}{\text{[EASY]}}\)
萌萌题.
不难想到按 \(b_i\) 排序, 枚举 \(c\) 求最优的 \(p\) , 然后我们定义 \(A_i\) 为如果定价为 \(a_i\) , 有几人付费.
那么付费的贡献为 \(\max\limits_{i=1}^{n}{(A_i\times i)}\) , 暴力维护是 \(\mathcal{O}(n^2)\) .
考虑分块, 设块总体被加 \(k\) 次, 散点被加 \(d_i\) , 对于同一个块, \(i<j\) 时, \(j\) 决策更优有,
\(k\) 不降, 单调队列维护下凸壳, 散块重构即可, 时间复杂度 \(\mathcal{O}(n\sqrt{n})\) .
\(\text{[CF773E]Blog Post Rating}\)
\(\color{green}{\text{[EASY]}}\)
啊, 好简单的题呢, 但为啥我不会做呢.
考虑暴力求一次 \(F\) 的过程, 不难发现, 是在某个位置之前一直单调减, 再之后一直单调不降, 显然 \(a_x \geqslant -x\) 的时候是分界点.
于是考虑二分这个分界点, 对于之后的值, 设 \(f_i\) 表到 \(i\) 这个点, \(F\) 的值, 不难推出 \(f_i = \min\{f_{i-1}+1,a_i\}\) .
展开得 \(f_i=\min\{a_x+i-x,\dots,a_{i-2}+2,a_{i-1}+1,a_i \}\) .
考虑多次操作, 线段树维护分界点位置, 即后缀第一个大于等于 \(0\) 的位置, 并维护后缀最小值即可.
时间复杂度 \(\mathcal{O}(n\log{n})\) .
\(\text{[CF1511G]Chips on a Board}\)
\(\color{green}{\text{[EASY]}}\)
被教育了, 被教育了, 被狠狠教育了.
记录位置的前缀和, 倍增 \(l\) , 合并的时候发现右区间的个数为奇数就直接异或上 \(2^k\) 即可.
时间复杂度 \(\mathcal{O}((m+q)\log{m})\) .
\(\text{[CF1605F]PalindORme}\)
\(\color{red}{\text{[HARD]}}\)
正难则反, 考虑计数所有不合法序列, 再那总数减去不合法的.
考虑如何刻画一个合法序列,
- 令变量 \(V=0\) .
- 从序列中选两个数 \(x,y\) , 使得 \(x \or V = y \or V\) .
- 令 \(V\leftarrow x\or V\) , 并删除 \(x,y\) , 重复做 \(2,3\) 步.
容易发现合法的序列一定可以删完, 不合法的一定删不完.
定义一个不合法的序列的最优子序列为经过这个操作之后的删除序列(若存在一个和 \(V\) 按位与之后等于自己的数, 就将其放在最优子序列的中间) .
我们发现不合法的序列剩下的数都满足, 去掉 \(V\) 为 \(1\) 的二进制位之后, 任意数均不为 \(0\) 且两两不同.
接下来 \(dp\) 解决问题, 设 \(f_{i,j}\) 表示长度为 \(i\) 的序列, 所有数的 \(\operatorname{popcount}\) 为 \(j\) , 的不合法序列数量, \(g_{i,j}\) 表示长度为 \(i\) 的序列, 所有数的 \(\operatorname{popcount}\) 为 \(j\) , 的序列数量, \(h_{i,j}\) 表示长度为 \(i\) , 所有数的 \(\operatorname{popcount}\) 为 \(j\) , 数非 \(0\) 且两两不同的序列方案数.
容斥计算 \(g,h\) ,
转移 \(f\) 可以枚举其最优子序列长度与 \(\operatorname{popcount}\) ,
时间复杂度 \(\mathcal{O}(n^2k^2)\) .
\(\text{[CF176E]Archaeology}\)
\(\color{green}{\text{[EASY]}}\)
照例先考虑无修改, 把所有点按照 \(dfs\) 序排序, 相邻两个之间的距离之和除二就是答案.
然后考虑怎么支持删点和插入点, 直接用 \(set\) 维护即可.
时间复杂度 \(\mathcal{O}(n\log{n})\) .
这个 \(\text{Part}\) 怎么感觉是在水啊, 这么多 \(\color{green}{\text{[EASY]}}\) .