高分AT/CF乱做第一弹
date:2023.4~2023.6
啥也不会,自闭了,黄队带我飞。
[ARC057D] 全域木/洛谷/AT
difficulty:3019
根据 kruskal 的过程设计 DP。设 \(f_{V,i,j}\) 表示当前完全图中的各个联通块的大小的可重集为 \(V\),目前考虑加入的边的权值为 \(i\),已经钦定好的边导致未被钦定的有 \(j\) 条加入到生成树中不会对答案造成影响。
- 如果当前边未被钦定出现在答案中,那么就不能选这条边,需要从没有影响的 \(j\) 条边中选一个代替它,转移为 \(f_{V,i,j} = j \times f_{V,i + 1,j - 1}\)。
- 如果当前边被钦定要出现在答案中,那么两两枚举目前状态下剩余的连通块,并将他们合并,记枚举的两个连通块大小为 \(x,y\),那么加入的边有 \(x \times y\) 中选择,并且会多出 \(x \times y - 1\) 条边加入到生成树中不对答案造成影响,转移为 \(f_{V,i,j} =\sum_{x,y \in V | x \neq y} f_{V - \{x\} - \{y\} + \{x + y\},i + 1,j + x \times y - 1}\)。
显然边界为 \(j < 0\) 时取到 \(0\),\(i > \dfrac{n \times (n - 1)}{2}\) 时取 \(1\),没有理想的枚举顺序,直接使用记搜记录。答案即为 \(f_{\{1,1,\cdots,1\},1,0}\)。submission
[ABC025D] 25個の整数/洛谷/AT
difficulty:3006
固定了 \(5 \times 5\) 的矩阵,考虑状压 DP,容易发现我们并不关心每一个数具体在什么位置,只关心他们之间的偏序关系是否满足限制条件,所以考虑从小到大填数。设 \(f_{S}\) 表示当前填数的状态为 \(S\),DP 值即为当前状态的总方案数,容易发现当从小到大枚举在一个格子中填数的时候,上和下要么都填了要么都没填,左和右要么都填了要么都没填,这个位运算容易做到。钦定了填什么的位置直接填上,没有钦定的暴力枚举,复杂度为 \(\mathcal O(n2^n)\)。submission
[ABC290Ex] Bow Meow Optimization/洛谷/AT
difficulty:3569
结论是贪心的想,从小到大排序后,将红色的前 \(\dfrac{n}{2}\) 个放在第一个序列,蓝色的前 \(\dfrac{m}{2}\) 个放在第二个序列一定最优。考虑权值只有 \(0\) 和 \(1\) 的情况,结论显然成立,那么推广到对于每一个 \(x\),将大于 \(x\) 的数看成 \(1\),小于的数看成 \(0\),那么原序列的答案大于等于每一个 \(x\) 的答案相加,对于每个 \(x\) 我们的策略相同,因此等号必然能够取到。submission
[CF599E] Sandy and Nuts/洛谷/CF
difficulty:2600
数据范围明示状压。设 \(f_{i,S}\) 表示在当前以 \(i\) 为根的子树中,选择了 \(S\) 这些点的方案数。转移非常显然 \(f_{i,S} = \sum_{j \in S | j \neq i,T \subseteq S} f_{j,T} \times f_{i,S - T}\),接下来考虑限制条件:
- 对于钦定了的边 \((x,y)\),他们必然在同一棵子树中,枚举 \(T\) 后判断 \(x,y\) 是否都存在于 \(T\) 中。这里存在一个问题是有 \(x\) 是 \(y\) 的父亲和 \(y\) 是 \(x\) 的父亲两种情况,所以要强行钦定以谁为父亲进行转移,防止算重。
- 对于钦定了的关系 \(LCA(a,b) = c\),如果当前枚举的根 \(i = c\),那么 \(a,b\) 不能在同一棵子树中;如果枚举的 \(T\) 中存在 \(c\),那么 \(a,b\) 也应该出现在 \(T\) 中。
边界为 \(f_{i,2^i} = 1\),答案为 \(f_{1,2^n}\)。首先需要枚举 \(S\),然后要枚举子掩码 \(T\),内部还需要再枚举转移到的点和判断是否满足限制,时间复杂度为 \(\mathcal O(3^n n (n + q + m))\)。submission
[CF235D] Graph Game/洛谷/CF
difficulty:3000
[CF1672G] Cross Xor/洛谷/CF
difficulty:3200
分类讨论。记 ?
个数为 \(k\)。
- 如果 \(n,m\) 同为偶数,将 \(i\) 行和 \(j\) 列的所有元素进行操作,相当于翻转 \((i,j)\)。方案显然为 \(2^k\)。
- 如果 \(n\) 为奇数 \(m\) 为偶数,一次操作会将所有列的异或和取反,因此有解的必要条件是所有列的异或和相等。发现操作 \((i_1,j)\) 和 \((i_2,j)\) 等价于对这两个点取反,答案计算是容易的。
- 如果 \(n\) 为偶数 \(m\) 为奇数。本质和上一种没有区别。
- 如果 \(n,m\) 同为奇数,单次操作 \((i,j)\) 相当于将所有行和列的异或和取反,易知必要条件是所有行和列的异或和相等。用前面类似的方法,同时操作 \((i_1,j_1)\)、\((i_2,j_1)\)、\((i_1,j_2)\)、\((i_2,j_2)\) 相当于对这四个点取反。将每行每列抽象成点,点权为行列中已知点的异或和,如果存在 \((i,j)\) 为
?
,那么对此行列连边,可以通过每条边确定是否翻转行和列,现在要求有多少种方法使得所有点点权和相等。经典做法是任意求出一棵生成树,答案为 \(2^{\text{边数 - 点数+ 1}}\),对每个连通块做一遍后求和即可。
[ARC134E] Modulo Nim/洛谷/AT
difficulty:3026
归纳。显然相同的数贡献是相同的,因此将序列中的元素放入集合之中考虑。
- 首先显然有 \(\{ \emptyset \}\) 为必胜局面,\(\{ 1 \}\) 和 \(\{ 2 \}\) 为必败局面。
- \(\exists a_i \equiv 1 (\mod 2)\) 为必胜局面,操作为选择 \(2\) 为模数使得对面进行一次 \(1\)。
- \(\exists a_i \equiv 2 (\mod 4) \wedge \forall a_i \equiv 0 (\mod 2)\) 为必胜局面,操作为选择 \(4\) 为模数使得对面进行一次 \(2\)。
- \(\forall a_i \equiv 0 (\mod 4)\) 为必胜局面,操作 \(12\) 为模数,若得到 \(\{ 4 \}\) 或 \(\{ 8 \}\),则改变操作进行取 \(3\) 为模数,转化为对手是 \(\{ 1 \}\) 或 \(\{ 2 \}\) 的必败局面。否则得到 \(\{ 4,8 \}\),对于对手来说这是一个必败态。
- 总结前四条得到序列中不全为 \(12\) 的倍数时,只有 \(\{ 1 \}\),\(\{ 2 \}\) 和 \(\{ 4,8 \}\) 为必败态,否则必胜。这部分时间复杂度 \(\mathcal O(1)\)。
- 全为 \(12\) 的倍数时数据范围中最多只有 \(16\) 个数,可以状压,dfs 递归解决哪些必败哪些必胜,用 DP 计数。这部分时间复杂度 \(\mathcal O(2^{16} \times 16 \times X)\)。
- 后者计数的具体方法为 \(f_{i,S}\) 表示处理了前 \(i\) 个数,选择 \(12\) 的倍数的方案为 \(S\),这里 \(S\) 的第 \(k\) 位直接表示 \(16 \times k\),然后转移是平凡的。
[CF1827D] Two Centroids/洛谷/CF
difficulty:2800
结论是设当前重心为 \(W\),则在 \(W\) 的儿子 \(S\) 子树中加入了一个节点,重心要么不变,要么变成 \(S\)。加入一个节点后只会对这个新节点的根链上的节点造成 \(+1\) 的子树大小影响,经典套路是在 dfs 序上这个节点的进入位置 \(+1\),那么此时一个节点的子树大小即为它进入位置和离开位置的区间和。维护这个过程,每次检测重心有没有改变,动态更新子树大小、当前重心、以当前重心为根的最大子树大小。套路的计算方法是记以重心为根其儿子的最大子树大小为 \(k\),总结点数为 \(n\),则答案为 \(n - 2k\),构造方法是往最大的子树里面塞叶子。综上所述,使用树状数组维护单点加以及 dfs 序上区间和,时间复杂度 \(\mathcal O(Tn \log n)\)。submission
[ABC208F] Cumulative Sum/洛谷/AT
difficulty:2772
[CF1648D] Serious Business/洛谷/CF
difficulty:2800
因为走出来的路径一定形如 \((1,1) \to (1,y_1) \to (2,y_1) \to (2,y_2) \to (3,y_2) \to (3,n)\),预处理出第一行的前缀和和第三行的后缀和备用。设 \(f_i\) 表示从 \((1,1)\) 走到 \((2,i)\) 且选择的区间恰好覆盖到 \((2,i)\) 的最大收益,然后枚举选择的区间,考虑转移。记当前枚举到的区间为 \(k\),转移分为两种,第一种是从 \(f_{l_k - 1} \sim f_{i - 1}\) 中的一个延续状态转移而来;第二种是 \((1,1) \to (1,y) \to (2,y) \to (2,i)\) 且满足 \(l_k \le y \le i\)。可以注意到这两个转移都是一个区间和的形式,所以上个线段树维护这个东西,就可以搞定第二行的 \(f\)。选择了覆盖这个区间,但是实际上可能并不会走满这个区间,但是最多也只有一个选择的区间右端点没有被走到,否则可以直接删去一个多余的区间,所以再设 \(g_j\) 表示选择了 \(j\) 这个位置从第二行走到了第三行。于是最后的答案即为最大的 \(f_i + g_j (i \le j)\),这个形式也是可以使用线段树维护的,有些类似 GSS 系列的区间合并。开两棵线段树做两次 DP,总复杂度 \(\mathcal O(n \log n)\)。submission
[CF1672H] Zigu Zagu/洛谷/CF
difficulty:2700
每次必定贪心的删除,形如 \(a[abab \cdots abab]b\)。设 \(00\) 和 \(11\) 的数量分别为 \(X\) 和 \(Y\),如果一次删除了一个长度为偶数的区间,\(X\) 和 \(Y\) 都会减少 \(1\);反之删除长度为奇数的区间,\(X\) 或 \(Y\) 会减少 \(1\),结论就是会优先删除偶数区间。剩下的一坨形如 \(aa \cdots a\) 就只能一个一个删,于是答案就是 \(\max{(X,Y)} + 1\),使用前缀和预处理做到 \(\mathcal O(n) - \mathcal O(1)\)。submission
[CF1361E] James and the Chase/洛谷/CF
difficulty:3000
首先考虑如何判断一个点是否是好的:建出以该点为根的 dfs 树,充要条件是树中不存在横叉边和前向边,因为返祖边成环了路径也是唯一确定的,所以无所谓。考虑在这棵树中其他点是好点的条件是什么:因为图强连通,所以必定有返祖边,充要条件即为有且仅有一条返祖边,若存在多条相当于以其为根的 dfs 树存在前向边,也不合法。如果一条返祖边连向的点 \(v\) 是好点,那么连出去返祖边的点 \(u\) 也是好点,因为 \(v\) 到其他点的路径唯一,\(u\) 到 \(v\) 的路径唯一,于是得出 \(u\) 到所有点路径唯一。根据 \(u\) 是好点当且仅当 \(v\) 是好点,我们可以在一棵符合条件的 dfs 树中得到剩下的所有好点,于是只要找到一个好点即可。考虑使用随机化,因为如果要输出好点,好点数量不得少于 \(\dfrac{1}{5}\),所以随机一次选取点失误的概率为 \(\dfrac{4}{5}\),随 \(T\) 次就有 \((\dfrac{4}{5})^T\) 的失误概率,选一个合适的阈值即可。随机选出来的点不能重复,原因参考生日悖论,所以可以直接对着编号序列 shuffle 一遍然后顺着测。代码取 \(T = 100\)。submission
[ARC104F] Visibility Sequence/洛谷/AT
difficulty:3213
最大值划分 DP。记 \(v\) 为区间 \([l,r]\) 最后一个最大值所在的位置,\(h\) 为序列中的值,那么 \([v + 1,r]\) 中的值必须要小于 \(h_v\)。设 \(f_{l,r,x}\) 表示 \([l,r]\) 这个区间中最靠右的最大值 \(\leq x\) 的方案数,注意到 \(x\) 的值域没有什么用,因为序列 \(p\) 所记录的是 \(h\) 序列的相对大小关系,所以离散化之后有 \(x \le n\)。考虑直接枚举这个最靠右最大值是什么,于是有转移方程:
这是一个区间 DP 的形式,枚举区间长度,枚举左右端点,枚举中间断点,枚举最大值是什么,复杂度做到 \(\mathcal O(n^4)\)。submission
为什么一定要设最靠右最大值而不能是最靠左最大值然后推一个类似的式子?因为这题的 \(p_i\) 是取决于左侧第一个比它大的位置,这样设计如果枚举左侧最大值,那么在右侧和它等大的一个最大值位置 \(j\) 将不再取决于 \(i\),而是 \(i\) 左侧一个更大的位置。即右侧不再独立于左侧,而是取决于左侧的某个值,因此计数出来是错误的。
[CF1285F] Classical?/洛谷/CF
difficulty:2900
单次询问整个序列,考虑乱搞。随机选择一部分数作为样本,所有的数每个和这些数两两求最大 lcm 作为权值,按权从大到小排序。取前两千个两两互相求 lcm,再取前 20 个个所有的数两两求 lcm,最后取最大值。需要吸氧和精细的调参,赛时这样写可能罚时到一分没有了/qd。submission
[CF1142E] Pink Floyd/洛谷/CF
difficulty:3200
考虑没有粉边怎么做,把所有点放到一个集合里头,每次随机从集合里头拿两个点询问,如果定向 \(u \to v\) 则删掉 \(v\) 将 \(u\) 放回,否则进行相反操作。这样反复操作直到集合中只剩下一个节点即为答案,操作次数 \(n - 1\)。如果粉边构成了一个 DAG,将入度为 \(0\) 的点放入集合中,做一个类似拓扑排序的东西,选取两个点询问删点后,将删掉点的粉边也删掉,然后继续加入入度为 \(0\) 的点,这样最后所有点要么通过粉边到达,要么通过答案点为根的绿边叶向树到达。扩展到普通情况,无非是 DAG 上套一些强联通分量,一个联通分量中的点是可以互相到达的,先缩点,依然加入入度为 \(0\) 的点,但是一个强联通分量每次只选一个点,删掉这个点之后再加入其所在的强联通分量中其它入度为 \(0\) 的一个点,直到整个强联通分量被彻底删除。时间复杂度 \(\mathcal O(n + m)\)。submission
[AGC054D] (ox)/洛谷/AT
difficulty:3426
[CF1610I] Mashtali vs AtCoder/洛谷/CF
difficulty:3100
[ARC142D] Deterministic Placing/洛谷/AT
difficulty:2938
[CF1814F] Communication Towers/洛谷/CF
difficulty:2700
来点数据结构典题,做法显然是线段树分治和可撤销并查集。考虑如何维护与 \(1\) 号节点的连通性,由于只需要知道历史上是否有任意时刻节点与 \(1\) 联通,所以每次遍历到时间树的叶子节点上,可以给 \(1\) 所在的并查集树的根标记值加上一,这样在撤销的时候再下放这个标记,就可以起到记录的作用,最后只需要查看每个节点的标记是否有值即可。但是这样可能造成的问题是有一个时刻某节点上有标记值,但是此时它和 \(1\) 号节点并不连通,所以合并的时候要先减掉合并过去节点的标记值,撤销时再加回来,这个技巧非常妙。submission
[CF117E] Tree or not Tree/洛谷/CF
difficulty:2900
没营养的数据结构。形态是基环树,先把环找出来,环和树分开处理。路径上边的“开关”等价于取反,答案即为总点数减去开着的边的数量,环比较特殊,如果整个环上的边都开着,还要给答案加上 \(1\)。环上无非两种情况,一段区间和区间的补集,后者拆成一段前缀并上一段后缀即可;树的话直接边转点树剖。剩下的二者都可以用线段树轻松维护,就是环的分类讨论很答辩,边转点细节挺多的。submission