noip2021 训练 1 做题记录
CF402E Strictly Positive Matrix
Description
Solution
考虑矩阵乘法的本质:
实际上类似于 \(Floyd\) 算法,枚举一个中间点 \(k\),计算从 \(i\) 到 \(j\) 的最短路,只不过把加法变成了乘法。求的不再是最短路了,但是我们依旧可以从 \(i\) 向 \(j\) 连边。
我们可以先对输入的矩阵进行一些处理,把大于 0 的点全都赋值为 1。这样就类似于邻接矩阵了。
对于 \(g_{i,j}\) 如果大于 0,就表示有一条从 \(i\) 到 \(j\) 的边,我们就给它连上,然后跑个 \(Tarjan\) 缩点,看是不是只有一个强连通分量即可。
CF427C Checkposts
Description
Solution
首先吐槽一句:不知道这题是怎么评到紫的。
观察题意:
如果有一个检查站在 \(i\) 路口,保护 \(j\) 的条件是:\(i==j\) 或者警察巡逻车可以从 \(i\) 走到 \(j\),并且能回到 \(i\)。
这不就是让我们求强连通分量吗?
确实是的,我们缩个点,对于每一个强连通分量记录一下最小的点权权值是多大。
然后把所有强连通分量里的最小点权加起来就是我们第一问的答案。
那第二问怎么算呢?
也很简单,我们把每个强连通分量里最小点权出现次数统计一下,然后求个积即可。
观察到这题要取模,取模就取模吧。
\(WA\)?!怎么回事?
看了一眼讨论区,发现第一问不用取模……
证明了看英文题面的重要性……
CF981D Bookshelves
Description
Solution
一个很明显的贪心,高位能选就选,因为如果当前位为 0,不管低位怎么选都不会高过当前位为 1 的权值。
所以我们从高到低枚举每一位。
假设当前答案为 \(ans\),枚举到了第 \(i\) 位,我们就要判断第 \(i\) 位能否为 \(1\),即判断能否凑到 \(ans' = ans\ |\ 2^i\)。
那么如何判断呢?我们考虑用 \(dp\) 判断。
类似于背包的过程,我们定义 \(f_{i,j}\) 表示前 \(i\) 本书,分为 \(j\) 个书架时能否凑到 \(ans'\)。
转移方程就是:
即 \(ans'\) 是 \(sum_i - sum_k\) 的子集。
转移完之后判断一下 \(f_{n,m}\) 是否为 0 即可。
CF617E XOR and Favorite Number
Description
Solution
暴力做法是 \(n^2\) 的,明显会 \(TLE\),考虑优化。
我们发现,题目是静态多次询问,不难想到莫队。
我们先做个前缀异或和,这样 \(l\) 到 \(r\) 的区间异或和即为 \(pre_r \wedge pre_{l - 1}\)。
然后分块莫队一下,每次增加或减少的答案为 \(cnt_{pre_l \wedge k}\) 或\(cnt_{pre_r \wedge k}\)。
CF161D Distance in Tree
Description
Solution
似乎各种做法都可以过,这里提供一篇 \(dsu\ on\ tree\) (树上启发式合并)的题解。
不会的同学可以看我的博客 浅谈 dsu on tree
题目要求我们求出长度为 \(k\) 的路径有多少条。
那么我们可以开一个桶 \(cnt_x\),表示深度为 \(x\) 的点有多少个,统计答案时 \(ans += cnt_{k - dep[x] + 2 * dep[topx]}\) (类似于树上差分的思想)。
然后修改就比较板子了,加入一个点的话就 \(cnt_{dep[x]}++\),删除的话就 \(cnt_{dep[x]}--\)
其他的就没有什么了。
CF464E The Classic Problem
Description
Solution
emm……这是我为数不多的黑题之一,所以来写篇博客记录一下。
我们发现边权过大,只能用高精度来算,但是这样的复杂度太劣了,无法通过此题。
观察到边权只能是 \(2^x\),所以我们可以给它压成二进制数,然后跑最短路时单点加。
我们再来考虑一下 \(dijkstra\) 需要哪些操作:
-
区间加
-
比大小
先来看区间加,如果第 \(x\) 位为 0,那么赋值为 1 即可,如果第 \(x\) 位为一,那么我们需要向上找第一个为 0 的位,然后这一段区间赋值为 0,第一个为 0 的位赋值为 1。
这个查找操作可以使用线段树上二分来实现,据说暴力查找也是可以过的,数据比较水。
那区间赋值为 0 如何实现呢?主席树似乎不太能支持修改。我们可以建一棵全 0 主席树,然后修改时直接把这棵全 0 的树拍上去。
再来看区间比大小,直接比较区间和即可。
然后就是代码实现了,个人认为非常有助于提升码力,也让我对主席树的理解更深了一步。
CF980E The Number Games
Description
Solution
向上面那道题一样的贪心,能选高位就选高位。
所以以 \(n\) 号选手为根,从 \(n - 1\) 依次向下枚举每一位选手,判断能不能留下。
如何判断呢?就是要判断从当前点到根节点要联通的话还需要增加多少个点。
如果小于还能增加的节点数,就可以:否则不行。
用树链剖分维护一下即可。
CF1101F Trucks and Cities
Description
Solution
看完题目后,首先想到的是二分,而然复杂度不是很优秀,并不能通过此题,但是 \(ywy\) 学长用玄学优化二分通过辣,太神啦 CCCCCCOrz。
我们要对题目进行转化:
如果有一辆卡车从 \(s\) 行驶到 \(t\),每行驶一格需要耗 的 \(c\) 油,最多可以加 次油\(k\),那么成功行驶需要的油箱的最小值为:以城市为端点,划分为 \(k + 1\) 段,它们中长度最大的段的最小值,再乘上 就是油箱 \(c\) 的大小。最后对于每辆卡车答案取一个 \(max\) 就可以了。
我们设 \(dp_{i, j, k}\) 表示把第 \(i\) 到 \(j\) 个城市划分为 \(k\) 段后,最大的一段的最小值。
那么转移方程就是:
emm……有点长,但这样的转移是 \(O(n^4)\) 的,还是无法通过此题。
考虑优化,不难发现 \(dp_{i, l, k - 1}\) 随 \(l\) 增大而增大,\(a_j - a_l\) 随 \(l\) 增大而减小,所以我们找中间的断点使得 \(dp_{i, l', k - 1} <= a_j - a_{l'}\) 且 \(dp_{i, l' + 1, k - 1} >= a_j - a_{l' + 1}\),然后转移即可,这样复杂度就变为了 \(O(n^3)\)。
另外,\(400^3\) 的数组我们也开不下,所以要把 \(k\) 滚掉。
CF1101G (Zero XOR Subset)-less
Description
Solution
线性基板子题,不多写了,主要我对线性基的理解也只是皮毛而已。
参考资料:
CF340D Bubble Sort Graph
Description
题意:给一个长度为 \(n\) 的序列 \(a\),让你在每一对逆序对上连边,求最大独立集。
Solution
我们就是要找两点之间没有边相连的点集中最大的那个。
分析题意可得,没有边相连意味着递增,所以找 \(LIS\)(最长上升子序列)即可。
树状数组维护一下。
CF274E Mirror Room
咕咕咕了,还没有写。