noip2021 训练 1 做题记录

CF402E Strictly Positive Matrix

Description

洛谷传送门

Solution

考虑矩阵乘法的本质:

\[c_{i,j} = \sum\limits_{k = 1}^{n}{(a_{i,k} \times b_{k,j})} \]

实际上类似于 \(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'\)

转移方程就是:

\[f_{i,j} |= f_{k, j - 1} \And ((sum_i - sum_k) \& ans' == 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

Luogu传送门

Solution

看完题目后,首先想到的是二分,而然复杂度不是很优秀,并不能通过此题,但是 \(ywy\) 学长用玄学优化二分通过辣,太神啦 CCCCCCOrz。

我们要对题目进行转化:

如果有一辆卡车从 \(s\) 行驶到 \(t\),每行驶一格需要耗 的 \(c\) 油,最多可以加 次油\(k\),那么成功行驶需要的油箱的最小值为:以城市为端点,划分为 \(k + 1\) 段,它们中长度最大的段的最小值,再乘上 就是油箱 \(c\) 的大小。最后对于每辆卡车答案取一个 \(max\) 就可以了。

我们设 \(dp_{i, j, k}\) 表示把第 \(i\)\(j\) 个城市划分为 \(k\) 段后,最大的一段的最小值。

那么转移方程就是:

\[dp_{i, j, k} = \min\limits_{l = i}^j(dp_{i, j, k}, max(dp_{i, l, k - 1}, a_j - a_l)) \]

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

Luogu传送门

Solution

线性基板子题,不多写了,主要我对线性基的理解也只是皮毛而已。

参考资料:

线性基 - OI Wiki

线性基学习笔记 | Menci's Blog

CF340D Bubble Sort Graph

Description

Luogu传送门

题意:给一个长度为 \(n\) 的序列 \(a\),让你在每一对逆序对上连边,求最大独立集。

Solution

我们就是要找两点之间没有边相连的点集中最大的那个。

分析题意可得,没有边相连意味着递增,所以找 \(LIS\)(最长上升子序列)即可。

树状数组维护一下。

CF274E Mirror Room

咕咕咕了,还没有写。

posted @ 2021-11-03 00:04  xixike  阅读(120)  评论(1编辑  收藏  举报