2021年第40周总结
10.4
CF 746
Problem B
考虑置换组,设 i i i 位置上的元素不可移动,那么:
i < x i > n − x i < x \\ i > n -x i<xi>n−x
此时解得的区间为 [ n − x , x ] [n-x,x] [n−x,x] ,那么题目就转换为分别对除这个区间外的两侧区间进行排序,最终查看整个区间是否有序。
Problem C
树上计算异或和,使用 a ⊕ a = 0 a \oplus a = 0 a⊕a=0 即可,发现最终情况只有两种,一种是奇数个连通分量,另外一种是偶数个连通分量
- 考虑偶数个连通分量,根节点的异或和必定为 0 0 0 。
- 考虑奇数个连通分量,根节点的异或和必定为每个相等的连通分量的异或和,故按照此数字寻找两条边可以去掉即可。
Problem D
交互题,二分答案。
对树上路径的二分我们可以考虑欧拉序列,欧拉序列定义为从根节点按照DFS的方式记录访问过的节点(包括返回节点),此时形成的欧拉序列中的任意两个相连的元素直接必定有一条且唯一一条边相连。
根据这个性质,我们可以通过创建欧拉序列进行二分,题目中的 GCD 跟数论毫无关系。
CF 744
Problem D
抵消问题,证明为何每次选择最大的两个元素。
情况一:存在且仅存在一个元素 a i a_i ai 使得 a i ≥ S − a i a_i \geq S - a_i ai≥S−ai ,其中 S = ∑ a i S = \sum a_i S=∑ai 。假设存在另外一个 a j a_j aj 也满足 a j ≥ S − a j a_j \geq S - a_j aj≥S−aj 。设 S ′ = ∑ k ≠ i , j a k S' = \sum_{k \neq i,j} a_k S′=∑k=i,jak ,那么 a i ≥ S ′ + a j , a j ≥ S ′ + a i a_i \geq S' + a_j, a_j \geq S' + a_i ai≥S′+aj,aj≥S′+ai ,解得 a i − S ′ ≥ b ≥ S ′ + a i a_i - S' \geq b \geq S' + a_i ai−S′≥b≥S′+ai ,前者是负数,而后者是整数,因此找不到这样的 a b a_b ab 存在。另外,设 S a = ∑ k ≠ i a k S_a = \sum_{k \neq i} a_k Sa=∑k=iak ,如果这次选择在 S a S_a Sa 中进行抵消,那么答案就变成了 S a − 2 + 1 = S a − 1 S_a - 2 + 1 = S_a - 1 Sa−2+1=Sa−1 ,如果在 a i a_i ai 和 S a S_a Sa 中进行抵消,那么答案就是 a i − 1 + 1 = a i a_i - 1 + 1 = a_i ai−1+1=ai 。因此最大的答案为 a i a_i ai。
情况二:否则,答案为 ⌊ S 2 ⌋ \lfloor \frac{S}{2} \rfloor ⌊2S⌋ 。如果最后剩下一个且为 0 0 0 那么结论成立。如果最后一个剩下为 1 1 1 那么结论为 S − 1 2 \frac{S-1}{2} 2S−1 结论依然成立。如果剩下的不为 1 1 1 那么就是情况一。
证毕。
Problem G
这是一个NPC问题,因此我们采用DP策略,设状态 d p i , j dp_{i,j} dpi,j 为结束点距离左边界的长度为 i i i 距离右边界的最小长度。
然后不难列出DP方程。核心还是枚举结束点距离左边界的长度。
算法最简单的也是枚举,最难的同样是枚举。
LC 26 双周赛
Problem D
一道摊还贡献的模板题,通过枚举作用效果来计算每个点的贡献数。
需要使用哈希表来记录作用效果对应的作用点,需要左右遍历两次数组。
LC 261 周赛
Problem C
一道非 Nim 博弈的好题,初看可能认为是 Nim 博弈,但是最后说如果都拿走了,那么不管是谁拿的都是 Bob 赢,因此终态和对手绑定,不是 Nim 博弈,此时我们就需要寻找规律。
通过两个方向考虑, Alice 想赢或 Bob 想赢,由这个题来看,从 Alice 想赢入手比较合适。
考虑 Alice 第一次拿 1 1 1 ,那么 Bob 第二次只能拿 1 1 1 , Alice 第三次拿 2 2 2 依次类推得到一个 1121212 … 1121212\ldots 1121212… 的一个序列。此时加上 0 0 0 的影响, 0 0 0 并不会影响余数的和,那么考虑最长的序列加上 0 0 0 的长度,如果是奇数并且最终还剩下 1 1 1 或者 2 2 2 说明 Bob 必输。
另外, Alice 第一次拿 2 2 2 的情况也同理,我们两种情况都判断一下即可。
Problem D
单调栈的变形题,原题是求长度为 K 的最小子序列。
考虑好何时弹出栈顶元素,何时将元素推入栈顶。
ABC 221
Problem E
树状数组+线性逆元,考虑位置 i i i 比 a i a_i ai 小的数有 a j a_j aj ,那么答案为 2 i − ( n + 1 ) = 2 i ∗ 1 2 n + 1 2^{i-(n+1)} = 2^i * \frac{1}{2^{n+1}} 2i−(n+1)=2i∗2n+11 , 由此可见权值树状数组加上线性乘法逆元即可。
杂题选集
LC 517
这个题的核心思路还是枚举,我们知道连续的一个线段 [ a , b ] [a,b] [a,b] 可以将一件衣服从 a → b a \to b a→b 或者 b → a b \to a b→a。 在最小操作中,我们枚举每一个点,计算这个点被线段覆盖了多少次,然后在所有点中取最大值即可。
考虑经过这个点的线段为由 L L L 部分到 R R R 部分的值,或者相反。端点并不需要考虑,因为他一定不会比他相邻的那个数的贡献大。
for (int i = 0; i < machines.size() - 1; i++)
{
lsum += machines[i];
rsum -= machines[i];
vec[i] += max(0, lsum - p * (i + 1));
}
上述为一段的代码。
10.5
ARC 126
Problem B
这是一个二维偏序问题,第一维按照 a i a_i ai 排序,如果 a i a_i ai 互不相同,那么问题等价于求 b i b_i bi 的最长上升子序列。如果 a i a_i ai 相同,我们可以使用一种常用的技巧,将 b i b_i bi 按照逆序排序,这样就能消除掉 a i a_i ai 相同的影响。
用树状数组维护最大值也AC了。
Problem C
这是一道关于GCD枚举的题目,设 x x x 是最大的GCD,由于 x = gcd ( a 1 , … , a n ) x = \gcd(a_1,\ldots,a_n) x=gcd(a1,…,an) ,所以 x ∣ i = 1 n a i x \mid_{i=1}^{n} a_i x∣i=1nai ,因此每个数都必须提升到 x x x 的下一个倍数上,我们计算 c o t s ( x ) cots(x) cots(x) 为答案为 x x x 的时候的花费数,我们枚举因子 k k k ,那么在 ( ( k − 1 ) x , k x ] ((k-1)x,kx] ((k−1)x,kx] 上的数字的贡献为 k x c − s kxc - s kxc−s ,其中 c c c 为在该区间的数字的个数, s s s 为在区间数字的和。此时我们可以用前缀和处理,因为我们枚举倍数,所以时间复杂度是 M log M M \log M MlogM ,其中 M M M 为最大的数字。
考虑 x > M x > M x>M ,此时的花费数为 N x − S Nx - S Nx−S ,让 N x − S ≤ K Nx - S \leq K Nx−S≤K ,那么 x = ⌊ K + S N ⌋ x = \lfloor \frac{K + S}{N} \rfloor x=⌊NK+S⌋。需要保证 x > M x > M x>M。
另外, accumulate
函数最后一个初始参数必须是 0ll
,否则将返回 int
。
ARC 127
Problem B
证明 2 2 2 开头的组是三进制计数是好证明的,最终我们通过 2 2 2 组去构造另外两个组,构造一组置换 210 → 102 → 021 210 \to 102 \to 021 210→102→021 这样就能满足题目中的条件。
Problem C
答案是类康托展开,计算每一位的对排名的贡献,每一位对排名的贡献就是 1 1 1 或者 2 n − 1 2^{n-1} 2n−1 ,我们只需要将 X X X 减一,或者查看该位是否是 1 1 1 。
有个结论:
对二进制计数器进行自增或者自减 n n n 次,总摊还时间复杂度是 O ( n ) O(n) O(n) 的。
故该题的时间复杂度为 O ( n ) O(n) O(n) 。
10.6
ABC 220
Problem G
计算几何,构造问题。是否能构成一个等腰梯形,这种问题的答案经常是枚举,很容易想到枚举顶点,但是时间复杂度会很高。我们可以枚举更小的图元来代表这个唯一的图形。一个等腰梯形可以由两个平行边唯一确定,所以我们可以枚举平行边。并且,一个等腰梯形的两个平行边的中位线一定是相同的,因此,我们可以枚举所有可能的平行边,记录下他们,这样我们就能构造出答案。
本题需要注意以下几点:
- 平行边的中点不能相等,可以额外判断一下。
- 使用小数是不安全的,选择 a x + b y + c = 0 ax + by + c = 0 ax+by+c=0 的这种直线形式即可避免小数,再者在计算中点的时候,我们可以不除以 2 2 2 同样可以保证答案的正确性。
此题给了我们计算几何构造问题的枚举优化解答,即枚举更小的代表元素,而不是有时枚举顶点。
10.7
ABC 221
Problem F
关于树的直径的问题,考虑树的中心分解。因为一棵树的中心只能有一个(即一个点构成的中心或者两个点构成的中心,分别对应直径是偶数和奇数的情况),之后,将中心(边或点)删去后,考虑计算每一个连通分量的答案。
当直径是奇数的情况时,将两个中心所连的边删去后,将变成两个连通分量,我们只需要在两个连通分量中找到到中心距离为 d i m − 1 2 \frac{dim-1}{2} 2dim−1 的点的个数即可。
当直径是偶数的情况时,将这个中心和所连的边删去后,将变成多个连通分量,计算每个连通分量到中心距离为 $ \frac{dim}{2}$ 的点的个数,然后进行计数即可。
CF 476
Problem E
按照每一位考虑,枚举在第 k k k 位上,存在与和 1 1 1 大于异或和 0 0 0 ,由于答案的长度只能是偶数,故 k k k 位前面的位必须都是 0 0 0 ,我们可以考虑用ST表维护前缀和,用前缀和维护异或和,通过DP记录最大连续的 1 1 1 ,每次通过二分选出最大的位置即可。
CF 422
Problem C
考虑对区间按照区间长度分类,为每一个长度都创建一个vector保存区间,然后每一个vector都按照 r r r 排序,建立前缀最小值,每次查询进行二分即可。
赛时第一想法是写主席树,想了很长时间的更简单的做法,最后还是写了主席树。主席树也RE了几发,看来主席树不RE几发是不会A的。
Problem D
赛时没看见 x x x 必须整除 n n n 写挂了,血亏。
首先一个显然的结论,就是每次分组的人数都是素数,那就让 x x x 为 n n n 的质因子即可。欧拉筛可以轻松维护。
证明可以用数学归纳法证明,发现每次分组分解成质因数的方案是最优的。
10.9
CF 747
Promble E2
考虑动态开点,或者按照给顶点更新到根节点的路径也行,赛中用的unordered_map百思不得其解为什么会TLE,后来被告知出题人故意卡unordered_map。
Problem F
数学构造题,考虑以 k k k 个为一个块,然后一块取一块不取即可。