2023 年 6 月训练记录
训练
中考终于考完了!!!
前面的题慢慢施工ing……
ARC107F Sum of Abs#
首先,我们现默认所有节点都被删了,可以用 的收益插入第 个节点。由于是求最大值,所以绝对值可以看作是限制有边的点同号。
我们考虑建图,对于第 个点,我们建两个点 和 表示取负或取正,每个点有点权,则 和 连边表示不能同时选。
对于一条边 , 和 、 和 连边表示不能同时选。
于是跑二分图最大独立集即可。
时间复杂度 。
记录。
ARC083F Collecting Balls#
对于球 ,将点 和 连边,表示这个球需要被行或列碰撞。则要求连出来必须是基环树森林,否则无解。
因为点数为 ,边数为 。若不全为基环树森林,则连通块中一定存在树,边数 点数,不可能存在完美匹配。
然后考虑对每棵基环树分开考虑,首先,树的部分边的方向是确定的,而环上只有两种情况。我们直接枚举,然后我们建出图,表示机器启动的先后关系(某台机器必须在某台机器后启动)。
注意到这个 DAG 一定是外向森林,所以拓扑序的方案数为 。
时间复杂度 。
记录。
[AHOI2022] 山河重整#
首先,有个比较显然的结论, 都能被表示出来当且仅当,将 从小到大排序,,可以通过归纳来证。
然后我们考虑如何计数,首先有个暴力 DP,令 表示用前 的数表示出的和为 的方案数。这没有什么前途。
我们考虑容斥,我们记 为 为 合法的方案数,DP 初值可以用类似经典方法优化,时间复杂度 。
注意到和为 的数中不同个数是 的。
如上图,每一列代表我选的数的值,注意到一种情况合法的充要条件:下面的行对应的列数 上面的行对应的列数 上面的行对应的列数 ;
于是我们枚举当前行对应的列数 ,无限背包转移大小为 的物品。
然后我们考虑转移,对于 ,我们枚举第一个不合法的位置 ,那么相当于要用 的数凑出 的方案数再乘上 。
于是,我们可以用和上面一样的方法,不过对于 ,背包内的物品大小至少为 。
注意到计算 时,我们必须把之前的 DP 值提前计算完成。这里可以使用类似半在线卷积,每次先求出前一半的 DP 值,再转移给后一半。
时间复杂度 。
记录。
[BJOI2019] 删数 #
本题是 AGC017C 的加强版。
我们沿用之前的做法,我们将出现了 次的数 ,变成 ,而本题由于有整体加减 的操作,所以可能会出现数 或 ,则需要把他们的贡献删除。
时间复杂度 。
记录。
CF1810F M-tree#
我的贪心做法不能套到这题,伤心。
先二分答案 ,则现在变成了第 点深度至少为 。
之前模拟赛出过一个题转化成了这一步,做法是维护一个堆,每次删去最大的 个叶子,然后加入这 个叶子中最小深度 ,然后把它放到值域上,就有一个递推式,不过这个递推式在本题非常不好维护。
我们考虑别的方法,类似得,我们注意到 个同一层的节点会占用一个上一层的节点,这很像 进制数的加法进位过程。
归纳下,就可以得到结论,满足条件当且仅当:。
也就是,,即 。
然后,我们只需要线段树维护下这个 进制数即可。
时间复杂度 。
记录。
[POI2014] SUP-Supercomputer#
神仙结论题。
重要结论:树中存在一个深度 ,使得深度 的点只需 次覆盖完,而大于 的除最后一次外其他每次都可以填充 次。
证明:在 上面的所有点如果不能连续填充 次,说明均摊下来每一层的点数肯定小于 ,这样的话一定存在上面的只用取 次的深度,那下面层数均摊大于 ,所以每次能填满 次,所以就是在找一个层数均摊为 的分界点,那么这种层数一定存在。
然后就是一个对于每个 ,求出 。
我的做法是现转成 double
,然后就是一个朴素的斜率优化了。
记录。
[USACO22DECP] Palindromes#
首先,无解是好判的。
考虑对一个串 算答案,相当于把 1 两两匹配,设有 个 1,第 个 1 位置为 。显然第 个 1 会和第 个 1 匹配,贡献为 。
然后,我们直接分长度奇偶,枚举 的匹配,注意到 对于同一种匹配,只会变化 次,所以直接维护即可。
时间复杂度 。
记录。
ARC086F Shift and Decrement#
注意到操作 A 次数是 的,于是考虑直接枚举总共操作 A 了 次,然后考虑在第 次操作 A 后进行操作 B 相当于在第一次操作 A 前进行操作 B 次。
于是,操作 A 总共只有 种:
-
在前 次操作 A 之前进行最多 次操作;
-
最后再进行若干次操作。
注意到种类 1 只会改变 二进制下的最后一位,且为 的是 排序后的一段前缀,于是考虑直接枚举。
注意到种类 2 是全局减 1,只会改变差分的第一项,而且可行的差分第一项是一个区间,所以,我们直接对差分数组开 map
,然后求区间并即可。
记录。
ABC304Ex Constrained Topological Sort#
首先,由于对于每条边要满足 ,所以我们可以让 。
然后,我们就从小到大枚举点,每次度为 且可以填的位置中 最小的。
证明:
时间复杂度 。
记录。
CF618F Double Knapsack#
高考题。
考虑先将选子集转化成选区间。
如果 ,则交换下 和 。
对于每个 找到最大的 满足 ,那么 。
这样的 有 种,所以根据抽屉原理一定能找到两个相同。
时间复杂度 。
记录。
CF566E Restoring Map#
做了半年,以下做法完全是自己想的,可能做烦了。
首先,现特判下菊花,以及两个点接所有叶子的情况。
我们对任意两个集合求交,那么对于一条边上的两个点,得到的集合为两个点和其有边点集的并,且集合大小至少为 ,对于其它情况要么为空,要么为一个点,要么为一个点和其有边点集。
对于一个点和其有边点集的情况,这样的情况要么大小为 ,要么出现多次。
那么现在,我们得到了一条边上两个点和其有边点集的并,我们考虑如何还原出这条边。首先,在点集内的这些点与这个集合的交至少为 (它本身和边的两个端点),于是我们再求出这些集合的交,不难发现恰好为边的两个端点。
不过还有种比较麻烦的情况,就是一条边有一个端点是叶子,这种情况下,两个点和其有边点集会退化成一个点和其有边点集。注意到叶子的集合会被它父亲以及它父亲相连点的集合包含(),所以我们可以找出哪些集合是叶子。
然后如果这个点集内已经有边的点数量多于 的话,我们对边集取交,就可以唯一确定它们的中心了。
否则,这个点集内已经有边的点数量为 ,由于判掉了两个点接所有叶子的情况,所以只有一个点非叶子的边只有一条。
于是就做完了!
使用 bitset
优化上述过程。
时间复杂度 。
记录。
ABC229Ex Advance or Eat#
超现实数板题。
对于不平等博弈,我们可以考虑用超现实数来解决,详见集训队论文。
struct Surreal {
ll n;
int d;
Surreal(ll _n = 0, int _d = 0) { n = _n, d = _d; }
inline friend Surreal operator + (const Surreal &x, const Surreal &y) {
int mx = max(x.d, y.d);
ll t = (x.n << (mx - x.d)) + (y.n << (mx - y.d));
int v = min(mx, __builtin_ctzll(t));
mx -= v;
t >>= v;
return Surreal(t, mx);
}
inline friend bool operator < (const Surreal &x, const Surreal &y) {
int mx = max(x.d, y.d);
return (x.n << (mx - x.d)) < (y.n << (mx - y.d));
}
inline friend bool operator > (const Surreal &x, const Surreal &y) {
return y < x;
}
inline friend bool operator <= (const Surreal &x, const Surreal &y) {
return !(y < x);
}
inline friend bool operator >= (const Surreal &x, const Surreal &y) {
return !(y > x);
}
inline friend Surreal operator - (const Surreal &x) {
return Surreal(-x.n, x.d);
}
inline friend Surreal operator | (Surreal x, Surreal y) {
assert(x < y);
if (x < 0 && 0 < y) return 0;
if (y <= 0) return -(-y | -x);
Surreal v((x.n >> x.d) + 1);
if (v < y) return v;
int d = max(x.d, y.d);
x.n <<= d - x.d;
y.n <<= d - y.d;
if (x.n + 1 == y.n) return Surreal(2 * x.n + 1, d + 1);
while ((x.n >> 1) + 1 < ((y.n + 1) >> 1)) {
x.n >>= 1, y.n = (y.n + 1) >> 1;
d--;
} assert(x.n + 1 == y.n - 1);
return Surreal(x.n + 1, d);
}
};
这是板子。
我们对于 DAG 上的一条先手可以选择的决策求出超现实数最大值,对于后手可以选择的决策求出超现实数最小值,最后将其 |
起来即可。
然后注意到每列是独立的,我们再把每列得到的超现实数加起来,最后再根据与 的大小关系来判断先手获胜还是后手获胜。
时间复杂度 。
记录。
CF578F Mirror Box#
首先,我们对图中 个点黑白染色,则一条边只会在黑点或白点之间。
重要结论:满足从任意一个边界段垂直射进网格中,光线会从相邻的边界段射出,同时网格中的每一段都被至少一条光线穿透,当且仅当黑点或白点连成一颗生成树。
首先,显然不能有环。其次要将边界上的边两两分成一组,每一组用一条封闭的折折线给围住,所以得连通。
于是,现将原图缩成一些连通块,然后再使用 定理,求出生成树个数即可。
时间复杂度 。
记录。
基于值域预处理的快速 GCD#
首先,任何一个数 可以被拆成 个数 每个数都满足以下至少一个条件:
- 为质数;
- 。
证明:考虑归纳,首先边界条件 是合法的。然后对于一个数 ,令其最小质因子为 ,我们先求出 的答案,令其从小到大排序为 。
若 ,则 的质因子个数不超过 , 的质因子个数不超过 ,所以 。
若 。设 ,则 ,所以 随 增加而增加,所以把 带入,可得 。
一个数和一个质数的 是好算的。然后,我们就预处理出 中两两的 ,可以递推。
时间复杂度 。
记录。
[APIO2021] 封闭道路 CF1119F Niyaz and Small Degrees#
感觉是比较套路的题,比较快地想出来了。
首先有个比较朴素的 DP,我们记 表示以 为根的子树,度数限制为 , 是否能和父亲连边的最小权值。
考虑 DSU on tree,注意到对于一棵子树, 中 只有子树大小种, 中 只有 的度数种。
我们现继承重儿子的答案,然后对于轻儿子,我们先选择 ,并将 放入 , 是一个堆。
那么我们处理 的时候,首先 中 的一定选,然后再选择前若干个使 满足度数限制。
时间复杂度 。
记录 2。
CF1662J Training Camp#
非常神仙的题。
我们考虑网络流。其中,源点连向所有填 的点,每个点连向同一行、同一列填入数比它大 的点,所有填 的点连向汇点。
则选 个点合法当且仅当 和 不连通。
证明:
-
必要性:
令 表示第 行值为 的列编号, 表示第 列值为 的行编号。
注意到一个值为 的不满足条件的点 (不妨假设所在行选的数比它大,所在列选的数比它小),一定会对应一条路径:,不妨成其为 简单道路。
由于 和 不连通,所以不存在这样的路径,所以方案合法。
-
充分性:
若 和 连通,则存在一条 到 的路径。但这条路径中的边可能经过多个行或列。
我们不妨假设,这条路径最后是连续在行上走。
首先,我们设到这个最后一段的起点为 ,所以第 行所删除的数小于 。
现在,我们对第 列所删的数分类讨论:
1. 如果删除的数大于 ,那么说明 这个位置不合法;
2. 如果删除的数小于 ,则可以把路径上的这一段删除,改为从 在第 列一直走到头。所以,对于这条路径,我们要么会得证,要么会减少一个拐点,最后只剩下一个拐点时就变成了一个点时,这条路径就退化成了一条 简单道路,则一定是情况 1。
得证。
实现的时候把每个点拆开,于是删点就变成了删边,那么跑最小割即可。由于要确保只能删 的点,所以,我们在原图一个点拆成的两点之间连边权 即可。
时间复杂度 ,由于是 dinic,所以 。
记录。
CF1168E Xor Permutations#
dls /bx
邓老师的论文例题。
考虑使用调整法,我们每次随机选一个未匹配的点,若存在它的一条匹配边满足另一个点也未匹配,则得到这样一组匹配;否则,我们随机它的一条边,强制其匹配,并将原先的匹配边断开。
实测非常优秀。
时间复杂度 。
记录。
CF1285F Classical?#
很巧妙的题,没能想出来。
我们可以将每个数的因数都加进去,这样,我们就把原问题转化为了计算 。
我们从大到小加入数,同时维护一个栈,从栈顶到栈底递增。由于若存在 的答案,则对于 的答案 就不需要统计了。
那么,若当前栈内有数与 互质,则可以弹出栈顶,并更新答案。
判断栈内是否有数与 互质,可以使用莫比乌斯反演:
表示栈内 倍数数的个数。
时间复杂度 。
记录。
CF1510H Hard Optimization [FJOI2022] 区间子集问题#
由于保证 条线段中,任意两条线段要么一个包含另一个,要么不交,则可以将包含关系建成一棵树的形式。
对于子树根 ,它的子段有两种情况:
- 在两个相邻儿子之间;
- 在一个儿子的内部。
对于情况 1,我们用坐标差来算;对于情况 2,我们考虑加一维状态,将贡献提前算。
我们设状态 表示 的子树内已经预留了 个子段,并且算进了答案。
第 个 0/1:若为 表示左端点带上了 的系数算进了答案;
第 个 0/1:若为 表示右端点带上了 的系数算进了答案。
于是就可以转移了。
时间复杂度 。
记录。
动态图连通性#
很巧妙的题,没能想出来。
首先,一条边被询问多次,要么是第一次被删,要么是一直没被删,于是我们对每个点 记 表示 号点第一次被询问的标号,若不存在则为 。
重要观察:询问相当于是让我们离线,找到一条按 排好序后字典序最大的路径。因为,能删就删,所以我们首先要求让最小值最大,然后要求次小值最大,依此类推。
首先,我们有个很无聊的暴力做法就是建主席树,然后哈希比较字典序,时间复杂度 。
当然,我们有一个非常简单的做法,我们令 是从 到 最优路径集合,那么按照 dij,我们通过边 用 更新 ,我们要按照 来排序,但现在我们有个结论是,我们只需要按照 排序即可。
证明:考虑 dij 过程中的两种转移 和 。不妨假设 。由于这两种转移同时存在,所以根据 dij,得到 ,那么说明 。
由于 ,所以在比较 和 时, 的元素可以忽略。于是,忽略后 ,所以等价于比较 、 的大小关系。
时间复杂度 。
记录。
CF1832F Zombies#
相当于是最大化 。
首先,我们把区间按照中点排序。
相当于是对原序列划分成 个区间,每个区间 答案是确定的。
我们考虑如何求出 ,表示对 这个区间内的区间与一个区间交总和的最大值。注意到 的左端点一定在 中,只有 中。
显然, 满足决策单调性,所以可以 预处理出来。
然后,我们记 前 个区间被分成 个区间的最大值,同样用决策单调性优化即可。
时间复杂度 。
记录。
CF241D Numbers#
逆天题,想了很久不会。
观察发现把一串数字接起来是一个类似随机的事情。
再是由于模数 很小只有 的范围,所以我们可以考虑只选用少量的数字。
经过实践,发现留下 就足够了,这样选取也能使异或和 的方案足够的多。
最后直接 DFS所有子序列即可。
记录。
ExPR 1 乘积 ABC239Ex Dice Product 2#
原来这就是 CF1801F 的原题,赛时一直不会,自闭了。
考虑把操作倒过来, 在自然数意义下当且仅当 。
于是,我们先数论分块把本质不同的 求出来,然后从小到大暴力 DP,每次也是数论分块求出整除后的数即可。
时间复杂度 。
记录。
ABC304G Max of Medians#
首先,我们二分中位数 ,我们把数建成 Trie。
一个重要的观察是:注意到 的时候, 是 的最高位,所以说 越浅, 越大。
所以,我们的思路是尽可能在子树内匹配。
我们分两类 DP:
-
一类是子树内匹配,设为 表示 子树内尽可能匹配,最少还剩多少个数没有匹配:
我们考虑优先在子树内匹配,因为跨子树匹配一定比子树内匹配优,也就是说我们求出了每棵子树剩下的数个数的下界,中间相差 的都可以取到。
根据 的二进制位来分类讨论:
- 若当前位为 ,则递归到两组子树跨子树匹配,进入情况 2,;
- 若当前位为 ,则递归到两棵树内分别先内部匹配,进入情况 1, 和 。
-
另一类是两棵不同子树的最大匹配,设为 表示 子树和 子树内尽可能交叉匹配,最少还剩多少个数没有匹配:
根据 的二进制位来分类讨论:
- 若当前位为 ,则递归到两棵子树的 和 ,进入情况 2, 和 ;
- 若当前位为 ,则递归到两棵子树的 和 先内部匹配,进入情况 2, 和 ,然后再讲剩下的尽量匹配。
最后求出最大匹配。
容易发现,过程中每个字典树节点只会被经过一次。
时间复杂度 。
记录。
AGC012E Camel and Oases#
注意到操作 的次数是 的,且每次操作 都会把能走到的都走到。
我们先预处理出 表示做了 次操作 时, 能往后最远到的位置、 表示做了 次操作 时, 能往前最远到的位置。
注意到我们最终相当于将 分配给一些位置,满足分成的区间内都可以互相到达。
那么我们就记 表示分配的操作 状态为 ,能从 开始往后覆盖的最远距离, 表示分配的操作 状态为 ,能从 开始往前覆盖的最远距离。
然后,判断 就相当于判断是否 。用差分,前缀和维护一下即可。
记录。
CF1842G Tenzing and Random Operations#
非常高妙的题!
考虑乘法分配律 。
我们记 表示现在已经计算出了前 个数的答案,限制了 个 的放置的答案。
然后,我们对乘法分配律选到的数分类讨论:
- ,;
- 之前选过的 ,;
- 新选过的 ,。
时间复杂度 。
记录。
CF1842H Tenzing and Random Real Numbers#
我们令 ,则 的限制变成了 ,也就是变成了 。
我们观察到这只与 的大小关系和 的正负有关。
下面假定 。
-
则 无限制, 为负。
-
则 无限制, 为正。
于是,我们考虑 DP,令 表示 前 大为 ,每次加入新数时判断是否可以去正、负即可。
记录。
ARC162E Strange Constraints#
简单题,但 VP 没过,鉴定为 🤡。
我们直接 DP,令 表示已经选了出现次数 的数,不同数的个数为 ,总数为 。然后,我们枚举选 个出现次数 的数来转移,中间需要用到组合数和斯特林数。
分析下时间复杂度, 的个数最大为 , 的个数最大为 ,所以总复杂度为:
倒数第二步用到裂项法计算。
时间复杂度 。
记录。
PR 5 双向奔赴 QOJ3301 Economic One-way Roads#
一个强连通分量一定可以由如下过程产生:
- 初始有一个集合 ,只有一个点。
- 每次加入一条链 ,要求 ()之间有边,并且只有 。
考虑 表示集合为 的最小代价, 表示链的点集为 , 的最小代价。
注意到 可以 ,但这是我们要求 。
时间复杂度 。
记录。
PR 9 比赛 QOJ1431 Joy#
模拟下发现,比赛整体是一个满二叉树的结构。我们可以先预处理出小多在最左侧、最右侧的答案,相当于求出小多在整个子树左侧、右侧的答案。
记状态 表示 子树内 分上述两种情况最终留下的概率。
求答案的时候考虑只有 棵子树被影响到,其他都可以用预处理好的值进行计算。
时间复杂度 。首先考虑预处理,由于是个树形背包的复杂度,每两个点之后在 LCA 出被计算一次,而总共只有 个点,所以是 的。考虑求值部分,单次查询,所有使用预处理子树的大小和为 ,所以是 的。
记录。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律