近期模拟赛题解与总结
内容大致包括(基本口胡的)每题题解、赛后总结、可能会有的周总结。
代码主要托管在 gitee 上面,直接粘上来太占空间了。
第一场模拟赛(2020.11.16)
第二场模拟赛(2020.11.18)
通过代码。
比赛总结:
- 进步:
- 第一第二题都解决了。
- 考试状态有所提升,受外界干扰的程度比较浅。
- 有了打草稿,写思路,规划时间的意识。
- 有待改进:
- 第二题调试耗时太长,导致后面的题目基本没有时间思考。因此要加快基础题的解决速度,提高准确度。
- 写骗分的时候要提高准确度,不然也是白搭。
- 要提高乱搞能力。
今天 T3 数据难造,于是许多人就水过去了 qwq 。
T1:剪头发
签到题,从小到大枚举 \(j\) 。此时有逆序对 \((x,y)\) ,那么必然有 \(A_y<j\) 。因此我们可以在 \(j=A_i\) 的时候加入 \(A_i\) 作为后面一个数产生的逆序对。时间是 \(O(n\log_2n)\) 。
T2: T 形覆盖
这不 T2 吗怎么都紫了。
首先发现,只有 Manhattan 距离 \(\le 2\) 的关键点才会互相影响。于是,我们可以将这样的关键点联系起来。
对于一堆连通的关键点,我们考虑它们合不合法。统计它们周围白格子(也即没有关键点的格子)。只要可用格子数量不小于需要的格子,那么就一定可以拼凑出来。
更进一步的,我们考虑最初的一个关键点,它有 \(4\) 个白格。现在加入一个,如果与它有公共边,那么就相当于增加了 \(2\) 个白格——因而如果要保证足够的白格,最多只有两个有公共边的白格。
如果没有公共边,那么就相当于增加了 \(3\) 个白格。于是,如果我们最终有 \(n\) 个连通的关键点,我们至多有 \(3n+1\) 个白格。如果白格 \(< 3n\) ,那么就 GG 了;否则,我们就考虑选取所有白格( \(3n\) 个),或者丢掉最小的一个。
T3: 迷途竹林
原题:[CF505E]Mr. Kitayuta vs. Bamboos
(准备写成单独的题解)
考虑二分答案,当前的答案为 \(L\) 。设第 \(i\) 棵竹子在第 \(j\) 天被砍了 \(c_{i,j}\) 次,那么合法的情况应该是:
其中第一层 \(\max\) 的前面部分表示的是 " 中途不被切没 " 的情况,后半部分枚举最后一次切没是什么时候,然后计算出最后剩余的高度。这里我们认为高度可以变为负数,因为枚举使得它不再重要。
以此我们可以得到 \(c_i\) 的后缀和 \(s_i\) 对于每一个 \(j\) 的下界。现在直接做是 \(O(nm\log_2W)\) 的。
但是,请注意总切的次数为 \(mk\) ,而我们现在的时间是 \(O(\max\{nm,mk\})\) ,我们需要将它优化为 \(O(\min\{nm,mk\})\) ,即,我们需要每次都在必须得切的时候再计算。前面我们可以得到:
将 \(s_{i,j}+1\) 代入计算即可得到下一次必须得切的时候。对于每个节点,我们可以用一个队列维护哪些竹子在当前点必须被切掉,并用一个变量记录当前剩多少次操作机会(这个机会下一次还可以用,毕竟是允许负数高度的)。时间是 \(O(mk\log_2W)\) 。
T4: 游戏
(准备写成单独题解)
首先考虑三维的 DP 。然后发现只有值的相对关系才重要,因此用差值做状态。
设 \(z\) 为最大值,那么考虑 \(f(a,b)\) 表示 \(z-x=a,z-y=b\) 的时候的期望。这里我们并不要求 \(x,y\) 的相对关系,因为我们可以对调再计算。
考虑转移:
然后发现只有 \(a\le 2\) 或 \(b\le 2\) 的时候有环,手解可以得出,合法情况下有:
另一边基本同理。此时如果做 \(O(n^2)\) 的递推即可得到 70 pts 。
考虑优化。对于存在边界的期望,我们可以尝试直接计算边界的贡献。也就是,对于 \(f(0)\) 和 \(f(1)\) ,我们用概率乘以贡献。注意到 \(f(a,b)\) 的状态,走到边界的过程中,始终走的是 " 日 " 字。因此我们可以解出走的正 " 日 " 的次数 \(p\) 和倒 " 日 " 的次数 \(q\) 。那么走到的概率可以方便地计算。贡献注意加上额外的步数(我们枚举了所有的终点,因此不需要考虑中途贡献系数不同的情况,重复计算帮助我们解决了这个问题)。额外需要注意的是,\(f(0)\) 的方案不能计算经过了 \(f(1)\) 的方案,减去即可。
时间是 \(O(n)\) 。
第七场模拟赛题解
通过代码。
比赛总结:
- 进步:
- T1、T2 的解决速度比较快。
我会乱搞骗分了。T3 成功通过乱搞做法骗到分。
- 有待改进:
- 做 T3、T4 的时候状态明显下滑了,注意不集中,思考时间太长、写的时间很短而收益很低。下次可以尝试给每道题限定 30min 的思考时间,如果不是感觉方向基本正确就先开始写代码。中途要注意适度休息,
多上几次厕所,说不定就可以想到新思路,或者突然就想通了。 - T4 骗分也挂掉了,准确度还是不够高,不能总是依赖对拍。
- 思路要更发散一些。 T3 明明已经到正解边缘了,还是没想到。
- 做 T3、T4 的时候状态明显下滑了,注意不集中,思考时间太长、写的时间很短而收益很低。下次可以尝试给每道题限定 30min 的思考时间,如果不是感觉方向基本正确就先开始写代码。中途要注意适度休息,
T1:bins
原题:[BalticOI 2010 Day2] Matching Bins
简单题,枚举 \(K\) ,把两段值分别丢到桶里。检查直接从大到小扫一遍,看是否有放不下的即可。
时间是 \(O(nm)\) 。
T2:inversions
原题:[CF414C]Mashmokh and Reverse Operation
简单题。一次交换操作会让所有跨越 \(2^k(k<q)\) 的段的顺序对变成逆序对,逆序对变成顺序对,于是对同一种段打标记,每次询问后直接统计。于是我们只需要考虑长度为 \(2^k\) 的段的跨越中点的顺序对和逆序对,归并排序预处理。
时间是 \(O((2^n+m)n)\) 。
T3:candies
原题:[BalticOI 2010 Day2] Candies
稍微难一些的题目。
求 \(P\) 非常简单。我们可以直接背包求出包含所有值的组合情况,接着枚举一个 \(B\) ,我们将它从可选集合中删去,也就是 \(O(nB)\) 的退背包。那么考虑当 \(Q\) 充分大的时候,我们的组合情况数可以直接翻倍。于是我们就求出删去后组合情况数最大的一个 \(B\) 作为我们的 \(P\) 即可。
接着考虑 \(Q\) ,可以发现一个 \(Q\) 合法的条件是,\(\forall S\subset U,\not\exist T\subset U,\sum_{u\in S}u+Q=\sum_{u\in T}u\) ( \(U\) 为全集去掉 \(P\) ),那么移项得到 \(Q=\sum_{u\in T}u-\sum_{v\in S}v\) 。可以发现这也是背包的形式,只不过符号有正有负。并且我们最终只需要知道某个值能不能凑出来,因此可以 bitset
优化。
时间是 \(O(n^2B)\) 。
考场的乱搞做法:
注意到最终的值域很小,只有 \(7\times 10^5\) ,而方案数是指数级别的,因此可能会有很多个可以凑出的数连在一起。我们可以将连起来的一段一起判断,而不需要拆开。退背包之后,处理每个位置向后的连续的 0 的个数和值非 0 的段,之后我们就可以枚举 \(Q\) 并进行判断。
贪心地想,我们应该将较长的段优先判断,而从小到大枚举保证了它可以在找到第一个可行值之后退出,因此它在随机数据下表现良好。
事实上,它不仅能过官方数据,还跑得飞快
T4:sheep
题目简述:
给定一棵大小为 \(n\) 的树,树上有 \(k\) 只 🐑 。如果在 \(u\) 上安排一位牧羊人,那么他会守卫最近的 🐑 不被吃掉(如果有多头就一起守卫)。求最少需要安排多少为牧羊人。
数据范围: \(1\le k\le n\le 5\times 10^5\) 。
这道题跟 [POI2011]DYN-Dynamite 有点相似。
首先可以预处理,得到 \(d_u\) ,表示 \(u\) 能覆盖的距离。
我们考虑在树上由叶子到根进行贪心。处理完一棵子树之后,我们得到了两个信息:该子树内所有未被覆盖的 🐑 的深度(可以发现不可能有深度不同的两只 🐑 ),以及子树内牧羊人超过根的最广覆盖范围。合并一颗子树,我们可以用当前树的牧羊人覆盖新子树,也可以用新子树的牧羊人覆盖当前子树,并更新当前树的两个信息。
合并完成之后,我们就需要考虑当前子树的根是否应该安排牧羊人。如果 \(d_{fa}>d_u\) ,那么必然有 \(d_{fa}=d_u+1\) 。此时如果放置在 \(fa\) 上面,那么同样能覆盖当前子树,并且更优,于是我们就推迟操作;反过来,我们在当前点上安排牧羊人。这也保证了不会有不同深度的 🐑 。
时间复杂度是 \(O(n)\) 。
第八场模拟赛(2020.11.30)
比赛总结:
- 进步:
- 仍然是简单题比较稳健,没有出锅。
- 面对今天的一组比较难的题,心里已经没有那么慌张了,证明心理素质在提高。
- 有待改进:
- T4 没想好就开始写,不仅是不熟悉的内容,而且写完了才发现自己伪了,浪费时间,结果半分没多骗到。
- T3 完全没有思路,然而骗分并不难,概率期望板块还是很弱。
- T1、T2 花费时间偏长,而且 T2 的时间基本都在打水漂; T3、T4 时间规划基本没有,因为心里觉得 T4 能行,所以 T3 基本就弃掉了,但是事实证明 T3 相对来说更容易骗分。一定严格按照时间来考。
第十场模拟赛(2020.12.02)
比赛总结:
- 进步:
- 解决了一道计数题目
虽然我觉得挺简单的。 - T3 骗分看起来写得不错
- 遇到后面题目比较难,保证了心态
没有崩掉,按照安排做题
- 解决了一道计数题目
- 有待改进:
T2 被卡常了呀 qwq。- T4 明明可以打表多得 30 pts ,偏偏没有想到这一点。
- 如果之后再遇到今天这种不太简单的比赛,尽量先把每道题的暴力先写好。
T1: bricks
原题:[CF1355E]Restorer Distance。
简单题目,可以发现函数可以直接三分。
或者发现在每一段内,函数最多由两段一次函数拼起来,所以可以在每个分界点计算答案。
T2: rgbgraph
原题:「美团 CodeM 初赛 Round A」二分图染色。
可以想到直接计算红和蓝的方案,但是会算重,可以容斥:
现在是 \(O(n^2)\) 。注意后面的那一部分等价于求一个完全二部图内任意匹配的方案数,可以直接递推。设 \(f_n\) 为一个左右大小均为 \(n\) 的完全二部图任意匹配的方案数,考虑新加入的两个点的匹配边可以得到:
现在就可以 \(O(n)\) 解决问题了。
T3: cyclesort
原题:「eJOI2018」循环排序。
首先可以发现,原图总可以被拆分成许多环。观察样例可以发现,我们可以用一次操作合并 \(n\) 个环,再用一次操作解决这个大环,仅仅带来 \(n\) 的多余操作下标。
现在问题在于,如何确定环该如何拆分?贪心地想,我们显然应该尽量拆分更少的环。对于多个值相同的点,我们可以将它们全部连到一个虚点上,再从虚点连向最后的可行位置。那么此时原先的一个环仍然是一个环,现在环尽量少等价于一个环尽量大,再次观察样例可以猜想是取欧拉路。所以按照这个意思跑欧拉路模拟即可。
输出方案可以直接构造,不再赘述。
T4: parentrises
原题:「BalkanOI 2018 Day2」Parentrises
考场上只有阉割版,也就是 \(P=2\) 的情况。
可以发现,此时必然是一个失配的括号可以和一个匹配的相同括号相配,两个染不同颜色,那么在隐藏了某种颜色之后仍然是良括号串。
换种想法,我们认为一个括号现在可以匹配上两个括号。也就是说,在从左往右做匹配的时候,我们认为一个右括号可以最多匹配两个左括号;从右往左,一个左括号最多可以匹配两个右括号。
经过转化,现在问题就简单了,可以直接设:
\(f(i,j,k)\):前 \(i\) 个字符确定后,前缀和为 \(j\) ,最小后缀和为 \(k\) 的方案数。
转移直接枚举当前括号。注意滚动数组优化空间。时间复杂度是 \(O(n^3)\) 。