代码源广附2026寒
Day 1
A 洛谷 P11663 勇者比太郎 2 / Bitaro the Brave 2
打完所有怪物也就是 \(x>a_i-s_i\),s_i就是到 a_i 时增加的所有力量。直接把序列复制一遍做前缀和,用线段树维护区间最大值即可。
B 洛谷 P14577 磁极变换 (没补)
阴,发现如果一块磁铁能吸上它自己就会撞毁。所以每一种颜色最多只有一块磁铁能存在,再考虑其他颜色的磁铁对当前磁铁的影响,\(O(V^2)\) V 为字符集大小。
C 洛谷 P10371 石头(没补)
单调栈+链表优化
D CodeForces 1743F Intersection and Union
拆位,考虑每一个位置在所有情况下对答案的影响。整理分讨逻辑的运算后发现对于 \([l,r]\) 内区间赋值,区间外 \(\times 2\),线段树维护。
E CodeForces 1732D2 Balance (Hard version)(没补)
记搜+神秘优化
F CodeForces 1777F Comfortably Numb
可以先用单调栈找到每个最大值可能出现的区间,区间内分成左右两半。用笛卡尔树的生成方法求区间一定是一个分治的过程,所以我们只需要对于每个找到的区间枚举小的半边就能获得类似启发式合并的复杂度,另一半用可持久化 trie 做,\(O(n\log^2n)\)
H 洛谷 P12598 参数要吉祥
看上去和历史的研究有点像,实则完全不然。但莫队依然可行,发现可以在莫队维护的 \(x\) 上根号分治,\(x>\sqrt x\) 不超过根号个,先在全局找到这些可能的根号个 \(a_i\) 然后在每个询问遍历这些 \(a_i\) 对应的 x 取它们的答案;若小于根号我们直接枚举这根号个 x,可以 \(O(1)\) 维护 \(c(x)\),枚举 x 求最大值。
I 洛谷 P12865 冒泡排序机 / Bubble Sort Machine
需要知道冒泡排序经过 k 轮后 \(\{a_1\dots a_i\}=\{a_1\dots a_{i+k}\}_{min_k}\),也就是前缀 i 的集合为前缀 i+k 的集合的前 i 小元素集(均为无序集)。这题的查询差分为前缀r- 前缀l-1;至于 k 轮后前缀 i 的元素和可以使用可持久化线段树。
Day 2
总结:没打暴力
A
分讨或者 dp,都挺难写。dp 可以写 3 维 i,j=0\1,k=0\1,做到 i,是否有出现过分隔,是否有出现过 \(b_i=1\),硬核转移
B
由于每个人出发时间不同且都走最短路所以只要从距离从大到小让人去送一定不会撞(不论送完后人是否停留),而且可以证明这是最小,答案为 \(\min\{dis+opposite\_rank-1\}\),在排名上线段树维护
C(没补)
可以线性模拟把 dag 建出来,再把 dag 上多余的边去掉,可知一定能修成一棵树。然后套用树上的 topo 序的计算式 \(ans=\frac{siz_{root}!}{\prod_{u=1}^n siz_u}\),或者递推计算 \(f_u:=\prod\limits_{u\to v}\times\frac{(siz_u-1)!}{siz_v!}\)。
D 原 code1 code2
注意没有顺序。建字典树,答案上界为字典树边数*2,在输出E后立马T就可以回到原点,考虑什么情况下能更优。就是E后重新从原点开始走到当前点,也就是说如果从下面重新B走上来比当前点直接走长度远。dfs u,我们遍历完 u 的一个子节点 \(v_1\) 后设最后在 lst 按了一次E,发现去下一次的子节点 \(v_2\) 无论如何也会经过u,所以考虑是从 lst 一直BBB上来还是从原点一路走下去。但是要求得最小答案的关键在于子节点遍历的顺序,最后遍历的子节点 \(v_{final}\) 有机会可以通过 u 回溯到 fa 时“从原点开始”这样走优化得更多,所以我们要对子节点 \(\{v_1\dots\}\) 排序,按照节点子树中深度最深的那个节点的深度排序。
A QOJ 15042 Card Game
发现如果 A 的第一个没有匹配那么后面的全部都不能得分总分为 0,若第一个能匹配则 B 也无法阻止得分总分为 1,模拟
B 洛谷 P9525 团队竞技 / Team Contest
神秘贪心。先对于三个维度每个维度建优先队列放入每个人,若有一个人在当前状况有至少两个维度都是优势则这人永远拉入黑名单,若当前状态不矛盾则break输出答案。正确性考虑如果这个人有多个优势则这个人跟当前情况的任何人都不能组队所以踢掉,这个状态也不会因后面的情况改变。
C CodeForces 2168C Intercepting Butterflies
第一次做通信。我们可以用前 15 位直接记录原来的 x,但是如果这 15 位被修改了该怎么验证呢?设原集合 \(\{s_1\dots\}(s_i<15),check=\oplus s\),将 check 如同 x 状压加入集合,由于 \(s_i<15\) 则 check 也只用 4 位,如果不同就用 check xor 集合里的就可以知道差了哪个。但是如果 check 被改了我们无法发现,所以用最后一格记录 popcount(check) 的奇偶,由于只改一位所以这三个东西必然有两个是对应的,判断即可。
D QOJ 14729 Organize the Bookshelf(没补)
一个 i 交换 \(a_i,b_i\) 没有代价,把每一位当成一个集合。贪心枚举 i,如果不匹配就找到下一个 \(a_i\) 的位置和下一个 \(b_i\) 的位置,哪个在前面就对哪个进行交换。这样就能保证 \([1,i]\) 位置全都是满足的,需要找的下一个 a,b 都在后面。
E 洛谷 P14662 异邻或居(没补)
利用 \(\oplus_{i=1}^n n\) 的特性在图上利用二分图三分图构造。
F 洛谷 P13778 =+#-
先要知道题目 c 如果能被做到那么时间则为 \(k-c+2p+1\),p 为在做 c 之前做了多少道题,某种做题方式可行需要满足 最晚被做到的题的时间 \(\leq n\),按照这个性质我们应该先尽量选最大的 \(c\)。发现若按先后顺序做了题 \(c_x,c_y\) 那么有 \(c_y\leq c_x+1\),设 \(c_i\) 的值域集合所构成的极长连续段集合 \([l_1,r_1],[l_2,r_2]\dots[l_i,r_i]\dots\),我们会从最后一个 \(l_i\leq k\) 的区间中一个题开始,然后可知我们每到达一个点就一定能把它所对应的连续段做完,而且这样做更优;做完当前连续段后跳到前一个段继续重复直到 ans 数量用完即可。我们二分答案 ans 表示我们做题的数量,判断用这种方法做的最晚结束时间是否 \(\leq n\)。
Day 3
A 洛谷 P14328 糖 2 / Candies 2
糖题建议升绿。一维的 dp 不可行,需要二维表示最后两个 选的位置分别在哪里,得到一个一维的转移,前缀和优化即可。
B 洛谷 P12678 Brooklyn Round 1 & NNOI Round 1 B - Gift
\(\sum b\) 较小可以考虑以此作下标 dp。考虑没有第二种情况所有总和为 \(\sum a\),每多选一个总和就能加 \(a_i\times(b_i-1)\),所以不用考虑 \(\sum a\)。按照 b 从小到大,\(f_{j+b_i}\gets f_{j}+a_i\times(b_i-1),j\leq b_i\) 这样复杂度就是 \(O(\sum b)\)
C CodeForces 1741G Kirill and Company
k 很小考虑对它状压,dp 每个点能否通过一条路经过某个关键点集合。跑最短路只对在最短路上的边建图,一定是 DAG 就可以用拓扑排序转移 dp,\(f_{i,j}\) 点 i 能否经过集合 j。
D 洛谷 P14459 Mystique as Iris
分讨考虑什么情况可行。如果有值 \(x\in[2,n-1]\) 则一定可行。考虑如果 =n-1 则只要进行 n-1 次操作每次都对该值 -1 就可以;如果 \(2\leq x<n-1\) 我们就可以不断删掉别的多余的数直到数组中只剩下 \(x+1\) 个值就转换为 =n-1 情况。
所有 \(\geq n\) 的值都只能通过直接设为 0 消除所以本质相同。若序列里有至少一个 \(\geq n\) 且有 1 相邻或者在开头或者在结尾则可行(推理方法就是一次可以删掉 {n} 或是 {1,n} 两种情况,不能让最后情况是 {n,1,n} 则就可行)。
E CodeForces 1720D2 Xor-Subsequence (hard version)(没补)
01Trie 优化 dp。
F CodeForces 2183F Jumping Man
很有意思。一个 trick 把相同元素出现次数平方和转换成元素相同的对数总和。这样我们用 \(f_{x,y}\) 表示链的顶点分别在点 \(x,y\) 时相同的链的对数,转移 \(f_{x,y}\gets [s_x=s_y](1+\sum_{a\in T(x)}\sum_{b\in T(y)}f_{a,b})\) 二维后缀和优化即可。
G AtCoder abc221_h Count Multiset
非常值得学习的一道 dp。看题可以直觉想到 \(f_{i,j}\) 表示总共 i 个元素总和 j。直接常规转移很困难。考虑在转移时分为将原来的序列每个数都加 1,有 \(f_{i,j+i}\gets f_{i,j}\);或者是考虑加入一个种类的数,也即先将原来的序列每个数都加 1,然后加入 \(\leq m\) 个 1,(这个“都加 1”不能和前一个转移合并因为若如此做你就不能控制此次加入 1 的数量)(这样子做 dp 也不需要控制“当前加入的数是多少”,而往往这个东西对 dp 的答案是没有什么影响的,但是由于在做背包的时候就有这样的遍历方式,有可能思维固化依然使用这种遍历方式,注意不要思维受限)。

浙公网安备 33010602011771号