2025 暑假代码源集训
2025/7/21 - 贪心构造交互思维
Code
CodeChef MINORPATH - Minimum OR Path
很典的按位贪心,将 ans 初始赋值为 \(2^{21}-1\),从高位向低位枚举每一位是否能删去
CF1763C - Another Array Problem
显然若 \(n>3\) 则可以将所有最大值以外的数全部改为 \(0\),那么答案一定是 \(n \times\max\{a_i\}\)
否则当 \(n\in \{1,2,3\}\),可以直接暴力求每一种情况的 \(\max\)
显然只有总和为奇数或最大值大于总和的一半才会无解。考虑 \(n=3\) 可以通过两次操作完成。于是可以找到一个 \(p\) 使得 \([1,p-1],[p,p],[p+1,n]\) 满足条件。直接计算即可
如果存在两个区间包含或相离,则答案容易求出。否则任意两个区间都相交,按照左端点排序,奇数选外偶数选内,可以证明这样一定满足条件
太玄妙了。
将偶数位反转,则相同的条件变成不同,则答案为 \(|cnt_0-cnt_1|\),将所有 \(2\) 平均的分给 \(0/1\) 即可
显然存在端点则返回答案为奇数,将每一列/行单独询问一定会得到两个奇数,对所在列/行二分即可,询问次数为 \(n-2+2\log n\)
最小值最大显然二分答案,使用优先队列存区间左右端点,贪心地选取区间即可
将每个字符串内部匹配,再贪心地将左括号更多的放在左边,右括号更多的放在右边,再次计算一遍匹配数
先选中最小答案,如果有重复则向右移。对于每个状态使用优先队列存下,转移只有右移,下移,当前左移下一行右移三种方式,枚举转移即可
考虑每个状态只有三种转移,即中间向左右跳以及离中间更近的向中间跳。类似二叉树,所以可以压缩路径求出 LCA 即为答案
2025/7/22 - 模拟赛 + 数据结构(1)
Code
首先每次选取的两个数中一定有当前最大值,所以可以使用 multiset 存当前所有值,每次 find 是否能凑出上次选取的数,贪心选取即可
因为最大值最小值可能连在一起出现,断环成链时要开三倍。然后很典使用单调队列维护当前最小最大值,统计答案时将序列分成若干最小值段计算即可
使用 set 维护所有港口,发现修改操作类似覆盖一个等差数列,可以使用线段树维护,直接下传标记即可
由于 \(b\) 是排列,\(a_i\) 每次只会增加 \(1\),所以开线段树存当前余数的最小值与答案。若最小值是 \(1\),则暴力向下更新,这样的次数不会超过 \(\displaystyle\sum_{i=1}^{n}\frac{n}{i}\)
考虑升序向可重集中插入元素,如果当前值超过原来能加到的最大值则结束插入,否则最大值加上当前值。使用主席树模拟这个过程即可
显然一个询问可以拆成四个询问最后容斥,把所有 \(4q\) 个询问做一次莫队即可
2025/7/23 - 数据结构(2)
Code
简单树状数组二分。由于一定有解,求出当前前缀和等于 \(a_i\) 的位置即可
开两个线段树,分别存推平后的速度和每个节点是否是火车头。对于每个询问二分修改的下标,在线段树上直接修改即可
令 \(f_{i,0/1}\) 为考虑前 \(i\) 位是最后以为是否被删除的方案数。使用单调栈求出 \(i\) 位之前第一个小于 \(a_i\) 的数,转移方程容易得出
CF2000H - Ksyusha and the Loaded Set
使用 set 和权值线段树维护所有相邻两个数的差,询问时直接查询即可
开一个 tag 记录线段树节点中是否所有颜色均相同,在使用一个全局 tag 记录所有颜色加上的总和
线段树存五个值:最大的 \(a_i\),最小的 \(b_i\),最大的 \(a_i-b_j(i<j)\),最大的 \(a_k-b_j(j<k)\),最大的 \(a_i-b_j+a_k\)。重载结构体加法后就是线段树板子
令 \(f_i=\displaystyle\min_{j>i,a_i+a_j=w}\{j\}\),则询问变成:\(\displaystyle\min_{i=l}^{n}f_i\le r\)。使用 set 维护 \(f_i\),使用线段树存后缀最小值即可
将询问容斥一下,发现前缀查询类似于全局查询。于是开一个主席树和一个权值线段树即可解决
2025/7/25 - 模拟赛 + 数据结构(3)
Code
CF459D - Pashmak and Parmida's problem
\(f(1,i,a_i),f(j,n,a_j)\) 容易递推求出,然后直接树状数组求(类)逆序对即可
CF1849E - Max to the Right of Min
枚举 \(r\),令 \(a_l=0/1\) 为 \([l,r]\) 是否满足条件。用单调栈维护比 \(a_i\) 大的位置与比 \(a_i\) 小的位置为 \(c_i\)。问题转变为区间 \(0/1\) 推平、区间求和,使用线段树维护即可
2025/7/26 - 字符串
Code
首先如果能得到 \(T\) 串,就一定能通过一次操作得到。求出有多少位置操作后可以得到 \(T\)。令 \(dp_{i,0/1}\) 为 \(i\) 次操作后得到 \(T\) 和其他的方案数。答案为 \(dp_{k,0}\),转移方程留给读者作课后习题
存下 \(T\) 的哈希值,用栈维护当前的 \(S\) 前缀字符串和哈希值,每次插入字符时如果出现了 \(T\) 则直接退栈
CF1721E - Prefix Function Queries
CF898F - Restoring the Expression
如果令 base=10,哈希值的加法可以直接代表数字的加法。因为和的位数一定为两个加数位数的较大值或较大值加 \(1\),所以可以枚举和的位数,用四种情况讨论加数位数的较大值。注意特判前导零即可
求出 manacher 数组后,令 \(l<r\) 为能删到的最右/左的左/右端点,答案为 \(\frac{r-l}{2}\)
将 \(a\) 数组做哈希,用线段树实时更新当前枚举到的 \(b\) 数组子串的哈希值,开 vector 记录答案即可
递推求出任意两个后缀的 lcp,存下所有子串,二分答案。每次 dp 令 \(dp_{i,j}\) 为将从 \(i\) 开始的后缀分成 \(j\) 段的方案数,后缀和优化即可
将字符串翻转,则条件变成首位不能被 ban。求出字符串的 height 数组。用两个单调栈维护 \(h_i\) 在哪个区间内是最大/小值。注意需要特判出现一次的串
CF1202E - You Are Given Some Strings...
建两个 AC 自动机,存所有 \(s_i\) 和 \(\text{rev}(s_i)\),令 \(a_i,b_i\) 为 \(t\) 的以 \(i\) 为端点前/后缀,即为 fail 树上节点到根的路径上有多少个 \(s_i\) 的结尾,答案为 \(\sum a_{i-1}b_i\)
2025/7/27 - 模拟赛 + dp(1)
Code
考虑 dp。令 \(dp_{i,j = 0/1/2}\) 为染完前 \(i\) 位,且此时 \(a_i=j\) 的最小花费。令 \(f_i\) 位第 \(i\) 位之前第一个 \(0\)。转移式子:
令 \(dp_{i,j}\) 为考虑了 \(i\) 个杯子总容量为 \(j\) 的最大储存水量,转移方程为:\(dp_{i,j}=\max\{dp_{i-1,j-(a_i-b_i)+b_i}\}\)
CF1077F2 - Pictures with Kittens (hard version)
令 \(dp_{i,j}\) 考虑前 \(i\) 个数选了 \(j\) 个且一定选了 \(i\) 的最大值,转移方程为 \(dp_{i,j}=\max\{dp_{u,j-1}+a_i\}(p\in[i-k,i-1])\)。这个式子容易用单调队列优化
2025/7/29 - dp(2)
Code
设 \(dp_{i,j}\) 为考虑前 \(i\) 个数和取模 \(h\) 为 \(j\) 的方案数,直接暴力转移即可
CF2000F - Color Rows and Columns
设 \(dp_{i,j}\) 为考虑前 \(i\) 个矩形得到 \(j\) 分的最小花费。枚举当前矩形得了几分暴力转移即可
令 \(dp_{i}\) 为前 \(i\) 行最多选几行,转移需要使用线段树优化。因为要求输出方案,线段树还要存下最大值所在位置
CF780F - Axel and Marston in Bitland
设 \(dp_{w=0/1,k,i,j}=0/1\) 为是否存在从 \(i\) 到 \(j\) 长度为 \(2^k\) 且以 \(w\) 开头的路径。枚举转移点用 bitset 优化转移。倍增计算答案
设 \(dp_{i,j}\) 为走完区间 \(i\sim j\) 所需的最小代价,将出发点设为 \((\min x_i,\min y_i)\),枚举中间点转移即可
令 \(dp_{i,j,k,l=0/1}\) 为前缀中有 \(i\) 个 V,\(j\) 个 K,\(k\) 个其他字符,最后一个字符是不是 V 的最小移动数,直接暴力转移即可
CF331C3 - The Great Julya Calendar
设 \(dp_{mx, n}\) 为删过的高位最大值为 \(mx\),当前数是 \(n\) 的最小步数。直接记忆化搜索转移即可
笑点解析:dp(2)
直接贪心,对每个人以 \(\max(s, a),a\) 做双关键字排序,然后顺序模拟判断
斜率优化板子题。设 \(dp_{i,j}\) 为用了前 \(i\) 个人,带回了 \(j\) 只猫的最小等待时间。对猫的出发时间处理一下(具体看代码),套斜率优化板子即可
2025/7/30 - 模拟赛 + dp(3)
Code
设 \(dp_{i,j}\) 为考虑前 \(i\) 个字符且不存在 \(\text{hard}\) 的前 \(j\) 个字符组成的子序列的最小歧义度。转移方程为:
可以滚动掉第一维
CF1336C - Kaavi and Magic Spell
设 \(dp_{i,j}\) 为从 \(s_{1\sim j-i+1}\) 前后插入后存在前缀 \(t\) 或是 \(t\) 的前缀的方案数。转移方程留作课后习题
2025/7/31 - 组合数学(1)
Code
由于二分到某一个点的路径是固定的,所以按照题目给的伪代码模拟一遍存下有哪些位置需要大于/小于 \(x\),计算排列数即可
P9306 - 进行一个排的重 (Minimum Version)
因为 \(p,q\) 是排列,每个数各不相同,如果两个排列中的 \(n\) 在同一个位置上,则把其放到第一位,答案为 2 (n-1)!,否则将其中的一个 \(n\) 放到第一位,最小值为 \(3\)。固定一位后计算 \(n\) 的另一边和另一个 \(n\) 有多少个数,求和
操作顺序显然是从上到下,从左到右一个一个清走,将图画出来可以发现就是一个旋转 \(45^\circ\) 的杨辉三角,直接使用上指标求和即可,答案为 \(\displaystyle\sum_{i=1}^{n}{{i+a_i}\choose{a_i-1}}\)
考虑容斥。计算出总共有多少加长的方式,枚举最长边和加长的总长度,计算有多少无法形成三角形的情况,直接减去即可
CF1929F - Sasha and the Wedding Binary Search Tree
因为给定的树是二叉搜索树,其中序遍历一定单调不降。对于每一个连续的 \(-1\) 段计算有多少种方式使序列单调不降。注意值域为 \(10^9\),组合数需要总和 \(O(n)\) 暴力求
CF1227F2 - Wrong Answer on test 233 (Hard Version)
连续两个答案相同的位置不用考虑,不会影响答案。令前后不同的位置有 \(x\) 个,枚举偏移后改对和改错的数量,可以得到能解决 F1 的式子 \(\displaystyle\sum_{i=1}^{x}{x\choose i}\sum_{j=0}^{\min(i-1,x-i)}{x-i\choose j}(k-2)^{x-i-j}\)。于是考虑容斥,将答案初始值赋值为 \(k^n\),这时枚举只需令改对和改错的数量相等,剩下的随便放即可
节点个数小于 \(n\) 的二叉树显然没有给定的树有趣,则答案为本质不同二叉树计数,即卡特兰数求和。再考虑节点个数相同的树,尝试递归求解,类似启发式合并的思路,我们只需要枚举大小较小的子树,左子树的答案可以直接累加,右子树需要容斥减去不合法的答案。左子树的答案需要乘有右子树的所有可能。
分类讨论,若 \(m=0\) 则答案为 \(1\),若 \(m=1\),则不能有连续的三个 \(1\) 或两个 \(0\) 出现,可以使用矩阵快速幂优化 dp 计算。对于大于 \(0\) 的偶数,则数组中奇偶性全部一致,即 F(m)=F(m/2)+F(m/2-1)。若 \(m\) 为大于 \(1\) 的奇数,则二进制加法下无进位,即 F(m)=F(1)*F(m/2)
2025/8/2 - 模拟赛 + 组合数学(3)
Code
显然染色方式只有 \(1\) 黑 \(2\) 白和 \(1\) 白 \(2\) 黑,所以基础染色方式有 \(\displaystyle{\frac{n}{3}\choose\frac{n}{6}}\)。再考虑环内的选择方式,如果三边相等,答案需要乘 \(3\);如果较小的两边相等,答案需要乘 \(2\);其它情况都只需要乘 \(1\)
CF1207D - Number Of Permutations
考虑容斥,总方案数是 \(n!\)。分别按照两维排序,求出满足一个数组非递减的方案。再求出两个数组均非递减的方案即可
CodeChef SEQGOODNESS - Sum of Goodness
考虑计算贡献,对于每个数计算当前位置,前面 \(i-1\) 个位置,与后面所有位置的方案数相乘即可
将数组当作排列计算,最后答案除以 \(\prod cnt_i!\) 即可。令 \(dp_{i,j}\) 为前 \(i\) 个数,选了 \(j\) 块作为偶数层的方案数。直接前缀和优化转移即可
Yukicoder 2206 - Popcount Sum 2
将询问离线,发现当 \(n,m\) 增减 \(1\) 时答案的变化量是好维护的,于是直接莫队
CF1924D - Balanced Subsequences
格路计数板子,答案即为 \({n+m\choose k}-{n+m\choose k+1}\)
2025/8/4 - 图论(1)
Code
也不知道和图论有什么关系,找到只出现一次的数放在首位,然后一位一位找满足条件的数
把思路反过来,把逃跑点当作起点,\(1\) 号点作为终点。在做 dijkstra 时如果当前还有怪物则直接 continue
把给定的邻接矩阵做一遍 floyd,让后做一遍简单 dp 即可,需要用前缀和优化
将每一行/列当作点,泥地当作边建二分图,跑匈牙利即可
2025/8/5 - 模拟赛 + 图论(2)
Code
CF1679D - Toss a Coin to Your Graph...
比较典的二分答案。每次 check 时脸上所有满足条件的边,用拓扑排序求出最长路。如果有环,则一定能走到 \(k\) 步
CF1213F - Unstable String Sort
一个重要的性质:同一个数在两个排列出现的位置之间的字符一定全部相等。于是可以在枚举时记录对方排列位置的 \(\max\),得到每一个区间之后直接放入字符即可
CF2000G - Call During the Journey
二分出发的时间点,用 Dijkstra 求是否能按时到达 \(n\) 点。转移时判断当前时间是否需要打电话即可
2025/8/6 - 树上问题(1)
Code
将 \(\text{size} - \text{depth}\) 从大到小排序,输出前 \(k\) 个的和即可
求出直径的中点,往下搜即可
比较厉害的题。考虑若 \(k=1\) 就是经典的换根 dp。又因为 \(k\le 5\),令 \(sz_{u,i}\) 为当前 \(u\) 的子树内,深度 \(\bmod k=i\) 的节点数量。每次换根时旋转子树暴力 \(O(k^2)\) 修改 \(sz\),按照正常的换根计算答案即可
典题。路径异或值不为 \(0\) 可以转化为前缀疑异或和全部不相等。用启发式合并容易维护子树答案
2025/8/7 - 模拟赛 + 树上问题(2)
Code
因为所有点权不同,子树内点权连续使答案最小。于是输出 \(\text{dfn}\) 序即可
考虑存在某个点的度数为 \(d\ge 3\),那么这个 \(d+1\) 个点的颜色需要互不相同。但只有 \(3\) 种颜色。于是答案不为 \(-1\) 的树一定是一条链。任取一条边随意染色,然后两边搜索求出构造方案即可
CF1790F - Timofey and Black-White Tree
由于染了 \(x\) 个点后答案是 \(\frac{n}{x}\) 级别的。于是可以每次暴力 BFS 找答案,可以证明时间复杂度为 \(O(n\sqrt{n})\)
我们钦定一个点为黑点的重心,由于重心的性质,答案为 \((n-1)k-\sum 2dep_i\),于是直接排序贪心选取即可
2025/8/8 - 数论
Code
因为 \(X_{i}-p+1\le X_{i-1}\le X_i\),所以可以枚举 \(X_1\),计算 \(X_0\) 的最小值
随便推推式子,令 \(f=\frac{a}{\gcd(a,b)},g=\frac{b}{\gcd(a,b)}\),那么 \(\gcd(a,b)=\frac{c}{cfg-d}\),直接枚举因数计算即可
将限制关系抽象成若干条链,则答案为独立集方案数。用斐波那契数列求出一条链的方案数,乘法原理算总答案
对于每组在回文串中配对的数,用 exgcd 计算每对的最小答案相加即可
整除分块求出质因数只有 \(2,5\) 的数的个数,容斥一下计算即可
注意到大于 \(22\) 的质因数最多只有 \(1\) 个,于是我们找出这个质数,将其他质数用一个整数压下来,做状压 dp 即可

浙公网安备 33010602011771号