抄题解,抄代码,抄别人的笔记。。
例题
定义带边权树的 -直径 为选出 个点使得将它们连通的最小连通块,边权和最大是多少(就是构成的虚树的边权和最大)。
- 点集 的 -直径一定是 的 -直径和 的 -直径这 个点中选 个。
- 若固定集合内一点求 -直径(需要确定剩余 个点),则剩下 个点一定在原本 -直径的集合中(类比两次 dfs 求直径)。对于前者就是以那个点为根长链剖分求前 大的长链(bzoj3252 攻略)。
P9623 [ICPC2020 Nanjing R] Baby's First Suffix Array Problem【口胡】
怎么 NOI2023 字符串和这个如出一辙啊/yiw
首先先加上所有 的,再考虑算错的有哪些:
对于第一种情况,满足 的 一定是 前面的一段区间,找到这个区间就变成静态二维数点了。
对于第二种情况,考虑在 上中点分治,在左半区间挂着若干询问二元组 ,查询右半区间有多少满足限制的 ,假设 位置的 height 后缀 是 , 位置的前缀 是 ,限制相当于 ,拆成 和 两种情况,那么就变成了静态三维数点问题。加上分治的一个 log 总的时间复杂度是 ,再具体写一下:
- 这部分实际上是二维数点。
- ,画出来是一个钝的小头在右下侧的直角梯形,把它差分成矩形 - 矩形 - 等腰三角形,对于等腰三角形数点,可以差分成带状 - 两个平行四边形,这样就都是二维(或者一维)偏序了。
[省选联考 2023] 填数游戏
o.O?
先把 已经能确定的值给填上,如果有冲突就无解。对于每个 只留下和 的交,然后 如果已经确定那么 也可以确定了。
对于这种大小 的还是考虑建图将 连边,此时每条边要选择一个端点进行匹配,那么对于一个连通块如果 就无解了,现在整张图被 连成了若干树和基环树。
看 Alice,对于每一条边可以选择让它与某个端点匹配时让 增加 1(可能两个端点都不能选择,可能只能选一个,可能两个都不能选,取决于 )。在基环树上,树的部分一定是和底端点匹配,在环上只有顺逆时针两种匹配方式,对于环上需要选择方向的边,贪心让两种方案较小的那一边的 增加 1 即可。
对于树的情况,考虑固定不进行匹配的那个点作为根 ,如果 Alice 将某条边选择某个端点就让这条边指向那个端点,那么此时 的大小就是内向边个数。问题转化成对树上若干边定向(有的边已经定好向,有的边不能定向),使得所有顶点为根时的内向边个数的最小值尽可能大。
对于需要选择定向的两条边 若构成这样的形状 ,那么将两者同时反向不会使得答案变小。所以最优解一定存在一个点 满足所有未定边都指向 。枚举这个点是什么再用换根算 就能做到 。
如果以某个点为根 dfs 的过程中枚举 ,用线段树在 dfs 序上支持区间加减全局最值,那么复杂度就是 的。线性其实也不难大概预处理一个什么东西的子树最值,dfs 的时候也得记一下子树补的最值就行。还是线段树不用动脑子好写一点!!
【来源不明】交流鸡
数轴上有 个点 ,对每个点确定一个半径 。其中 能到达 当且仅当 ,如果 能到达 且 能到达 那么 可以直接交流,如果 和 能直接或者间接交流,那么 可以间接交流。
合理地确定 使得任意两个点能够交流,并且 能够到达 的点对 尽可能少。
分析一下性质,首先如果 恰好到达 ,如果 不能到达 则 调整更小不会更劣,启发我们找一个划分方式区间 dp,左右两区间互不影响这样子。
假如确定了全局 最大的点是 ,那么 左右两侧独立了,因为如果 左侧某个与 右侧某个直接到达,那么肯定也可以经过 间接到达。假如确定了 是 所有可能的 中第 小的,那么变成两个子问题 和 。其中 表示仅区间 和 要连通,并且 选择的是第 小的 ,最小代价是多少, 类似。
此时单独考虑 ,考虑枚举最靠左的能直接到达 的点是 ,它选择了第 小的 。那么同样不需要考虑 左侧和 右侧直接到达的情况,如果 左侧有某个点 恰好直接到达 右侧点 ,如果 可以相互到达那么 可以缩小,否则 可以缩小。
那么左半部分可以递归到 ,而右半部分的子问题相当于区间 已经保证 可以直接到达,求连通的最小代价。那么一定存在一个分割线使得左侧全都直接或间接到达 ,右侧全部直接或间接到达 ,那么就是 dp 出一个 即可。
处理 是 的已经可以接受,问题在于 的处理是 的。
CF1984G Magic Trick II【口胡】
的判断是简单的。
考虑 ,对于此类问题的技巧是用一个 #
分隔符表示它下一个位置是排列的开头,然后将操作转化成和 #
有关的操作。手玩发现此时 的操作变成了:
- 将
#
左移两位,或者右移两位。 - 将
#
右侧两个数 swap,然后右移一位;左侧同理。 - 将
#
两侧的数 swap,然后选择一个方向移动一位。
此时对于 为奇数,第一个操作可以将 #
转到任意一个位置,然后一次 2 操作一次 1 操作可以让 #
保持在 1 左侧第二位的情况下让 1 向左移动一位,于是就可以冒泡排序了。
当 是偶数的时候,首先 可以直接把最大的数扔到末尾,从而 变成上述情况。现在考虑 是偶数 的情况。此时考虑这个操作逆序对个数奇偶性一定不会变(每次操作相当于 次 swap),那么逆序对个数为奇数则无解。然后发现上面的操作可以用三步凑出来一个 “ 将 #
右侧三个数循环左移一位 ” 这个操作,用这个冒泡排序就可以了。
[AGC025D] Choosing Points【口胡】
看上去就像是鸽巢,那么考虑距离为 的点对连边连出来是二分图,《在 的左部还是右部,在 的左部还是右部》可以分为四部分,取 size 最大的。
证明,若 为奇数,则 为奇数,不会连出奇环(转一圈回来的 应为 );若 ,那么 ,同理不会连出奇环;若 ,继续分类 的情况不会连出奇环,再考虑 的情况 ... 而 是有限的,从而归纳得证。
[JOISC2022] 复兴计划【口胡】
多次询问 ,将边 的权值改为 ,求最小生成树。
权值相同时选编号更小的。每条边的存在时刻是一个区间,因为当它权值下降时它不会被踢出,被踢出时权值在上升所以一定不会再加进去。求出 使得 时第 条边在最小生成树中,那么询问就变成了 即可离线扫描线解决。
如果它可能在最小生成树上,那么 的时候一定在,那么就要求出 时到哪儿不在了, 到哪儿不在了。对称,考虑左侧,相当于从左到右扫,维护这个前缀选边尽可能靠右的生成树,加入 时它能踢掉的最小的权值是 ,那么 就是 第一次比某条边更优从而进入最小生成树的时刻。这里可以暴力也可以 LCT。
[AGC021D] Reversed LCS【口胡】
的回文子序列一定是 的公共子序列,而 的公共子序列一定可以调整出来一个等长的回文子序列。所以 就是 的最长回文子序列,对这个 dp 就可以了。
Hedge Maze
先考虑如何判定 是否能走到 ,找到 能够走到的 的 最小的点,以及能够走到的 最大的点,首先需要满足 在这两者之间。然后发现它大致相当于尽可能向右走和尽可能向下走形成了一个轮廓,要求 被包含在轮廓之间,这是一个必要条件。
另一个必要条件是以 为终点的最长路需要 。然后发现这两个必要条件在一起就充分了,因为以 为终点的这个最长路一定能抵达轮廓,再从轮廓上走就到达了 。
对于正解,枚举 走了 步,那么也确定 走了多少步,并且确定它们共同到的终点在 的这一条斜线上,我们断言如果能碰面,那么 格子能够走到最靠上最靠下的点,这四个点一定有一个是能同时被 到达的。考虑如果 的轮廓有交,那么中间交点处开始就都可以到达,于是交点之后的轮廓的端点也能到达;如果它们的轮廓相互包含,那么较小的轮廓之中的点一定是轮廓端点最优(中间点的最长路不会优于轮廓端点的最长路);如果轮廓无交,那么不能它们碰面。
于是可以二分 ,用倍增确定这个轮廓的端点。总的时间复杂度是 。
P9734 [JOISC 2021 Day2] 逃走経路 (Escape Route)
如果是在同一天到达,那么考虑整体时刻不断 +1 直到某条边卡到界,枚举这条边,从这条边以 时刻走到 的到达时刻是 ,以 时刻倒着走到 的时刻是 ,那么答案就是 ,要求 。从每条边开始跑最短路,预处理对于每对点而言将所有边按照 排序记录后缀 的 即可。
如果不同天到达,假设第一天最后走到了 ,判定是否第一天就需要从 倒着走到 的时刻 要 ,然后需要解决从 点 时刻出发最少多少时间到达 ,直接从每个点开始跑最短路预处理这个 ,那么同样是查询 的 的 ,预处理排序后记录后缀 。
P7213 [JOISC2020] 最古の遺跡 3
先假定同一高度的柱子有区分,最后再除以 。从后往前考虑每个石柱 ,每次找 还未标记的值 ,那么 最后会被震成 ,如果找不到说明 湮灭了。那么 dp 记录最大的 满足 都被标记了,如果来了一个湮灭石柱,它有 种可能,这里 是已经出现了几个湮灭石柱。
否则这个石柱要标记某个值,如果 未更新则将其值的确定延后到后方处理,否则考虑 增加了 ,那么相当于在之前还没有确定值的石柱中再选出 个,对于这 个石柱相当于《将 全部标记并且最后一个标记的是 》方案数。
令 为《 个石柱将 全部标记并且最后一个标记的是 》的答案, 为《 个石柱将 全部标记》的答案, 就可以递推出来了。
这样总的 dp 复杂度就是 。
P8329 [ZJOI2022] 树
发现如果钦定叶子很好算,问题在于一个点不被钦定叶子它既有可能是叶子也有可能非叶子,[叶1],[叶2],[非叶1],[非叶1]
分别表示是/不是 1/2 号树的叶子,这里是艾弗森括号。那么一个方案的权值就是 ([叶1][非叶2]+[叶2][非叶1])
。[非叶1]=(1-[叶1]),[非叶2]=(1-[叶2])
,推得 [叶1]+[叶2]-2[叶1][叶2]
,也就是钦定它为其中一棵树的叶子,容斥系数为 1,钦定它同时为两棵树的叶子,容斥系数为 -2。
于是可以 dp 表示 为考虑了前 个点,前面有 个被钦定为叶子,后面有个 个没被钦定为叶子,带权值的方案数总和是多少。时间复杂度 。
QOJ5094 小 H 分糖果
一定是不断挑最大的,于是二分一个 ,假设 的数总和为 ,个数为 ,那么都删到 需要满足 ,二分找到最小的 之后会剩下 次操作,一定有 ,于是找到 后这部分的贡献也是好算的。整体二分,那么只需要支持单点修改,根链求和,转成子树修改单点求值即可仅用树状数组解决。总复杂度是 。
TopCoder 14379 RPSRobots
判定序列 是否合法,可以令 ,这样子 之间合法当且仅当 与 循环卷积之后所有点值都相等。对于 次多项式 个点值都相等,根据代数基本定理,说明这个多项式就是常函数,从而等价于 与 (除了 处的)非零值不交。
这里需要发现 第 位非零等价于 第 位非零。写出式子:
共轭不影响是否为 0,所以就对了。这样子就彻底转化成计算选出若干集合满足两两无交的方案数,可以 解决。
CCO2024 P3 Summer Driving
答案是 。对于 ,设 表示 均走过,Alice 先走的答案; 表示 Bob 先走的答案。为了能够更好转移 Bob 走到某个祖先而停止,令 表示当前 Alice 在 ,并且 这条边不能走,答案是多少。列出转移之后大部分都可以直接树链剖分解决。
唯一不能树剖的转移是 Bob 走到某个祖先再往外走,也就是 需要查询 的邻域中非 祖先且非 子孙的点的 的 。dp 的转移顺序是按层从下往上扫描线,查询处理完一层的 会更新出上面一层的 。
对于这种邻域问题还是考虑树分治,考虑边分治。如果分治中心 在 子树内那么不需要转移;如果 和 没有祖先后代关系那么全部都可以转移;如果 是 的祖先,那么在另一棵子树中,是 的祖先(同时也是 的祖先)一定是一条根链,那么维护两个数据结构,一个是不含根链的,一个是含根链的。对于非祖先的那棵子树就只需要维护一个数据结构了。
这样总的时间复杂度就做到了 ,空间复杂度需要在每个分治中心都开 3 棵线段树所以是 ,常数还是比较大的...
更好写的做法是二分答案,这样子就不是最优化而是判定是否有 0,1,就更好写了/fn
P9530 [JOISC2022] 鱼 2
考虑如何校验一个鱼是否不能活到最后,那么充要条件就是存在一个包含它的区间 满足区间和 (称为被 ban 区间)。
不能直接数点的问题在于询问的两侧,由于单独提出 之后相当于将 视为 ,所以可能出现以 作为 的极长被 ban 区间 ,可能出现以 作为 的极长被 ban 区间 ,可以直接二分出这两个端点,对于再往中间的部分就不会被 影响,那么就是完全被包含在 内部的被 ban 区间会 ban 点,没被 ban 的点才会被贡献进答案中。
现在考虑单点修改 会对哪些被 ban 区间产生影响。
仅考察 的被 ban 区间,若 相同,那么不同的 从右往左一定满足 递增,并且每次权值至少 ,所以固定其中一端点时被 ban 区间只有 个,那么单点修改 的时候直接将 和 的被 ban 区间全都暴力重找一遍即可。
再考虑包含 的被 ban 区间,由于被 ban 区间不会相交,所以它们一定是包含关系,同理包含关系的区间每扩张一次(还是两次)权值至少 ,那么包含 的被 ban 区间也至多有 个。也将这些端点拉出来重新再找一遍即可。还要情况是将它改小可能会增加包含它的区间,直接 轮左右二分找就行。
每次要对 个端点重新找被 ban 区间,假如是对左端点找右端点,那么需要 ,线段树上直接嗯递归把这 个可能的 找出来就行。找到被 ban 区间,为了询问还要将这些被 ban 区间进行一个区间 +1,支持区间查询 0 的个数,在询问的时候临时删掉包含询问左右端点的区间。于是现在复杂度是 。
P9529 [JOISC2022] 一流团子师傅【口胡】
shuffle 编号,每次尝试找出一个串。从前往后一个个试着删,如果答案依然是 那么可以加入到串串中,否则需要留下来。(相当于保持这个桶的最大高度始终是 )
确定性做法:考虑直接从前往后维护 个串已经包含了哪些,每次尝试把一个团子加入到一个串中,如何校验?就是看只删这个串,剩余的桶的最大高度是不是 。现在考虑快速定位这个串,那就二分,判定当前这个团子是否能加入串的集合 ,就看只删 中的串,问出来的答案是不是 。
P9523 [JOISC2022] 复制粘贴 3【口胡】
首先能看出是一个区间 dp 的状态,考虑如果要用 凑出 , 出现的位置可能有交,但是每次贪心选择最前面一次出现就是对的。最边上的散点可以用 ,所以仅需要考虑 出现在头尾的转移。反过来考虑由 转移 ,相当于 初始令 ,每次从 及以后找 下次出现,进行转移。为了实现快速找 在 下次出现位置这个事情,预处理的时候对于每个相同的串拉出来,双指针一下就行。时间复杂度是 。
P9528 [JOISC2022] 蚂蚁与方糖
用 Hall 定理算最大匹配数,相当于选出若干区间 ,用 中的 1 个数减去 中 0 的个数,还要求区间之间互不干扰,求最大权值和是多少,用全局 1 的个数减去它就是答案。
利用前缀和进行转化,令 为 《 的 1 个数》《 的 0 个数》, 为 《 的 1 个数》《 的 0 个数》。那么答案可以表示成选出一些位置 ABABABAB..., 的最大值即为所求。这里松了一下条件,因为如果 B 后面一个 A 挨得太近是一定不优的。
考虑修改。后缀加减的动态 dp 肯定是不能做的,得考虑这里的特殊性质。线段树维护 表示 节点代表的区间内选出了一个子序列,最左/右是 A/B 的答案为多少。
如果在 位置加入了 1,那么会将 的 都加 ,此时对于一个区间来说, 的增量唯一地被后两维 而确定,也就是固定后两维的所有可能的方案,增量是固定的,所以可以直接打 tag 加。
如果在 位置加入了 0,那么会将 的 都减 , 的 都减 。共同减的那一段后缀可以和上面一样直接打 tag。然后是会对长度为 的 进行区间减,根据最初的分析,B 后面跟着的 A 中间距离一定会 ,否则不优,所以长度 的区间减也可以直接打 tag。这样总的时间复杂度就是 。
P9521 [JOISC2022] 京都观光
没啥很神奇的理解,就是题解做法,需要多解释一嘴的就是它前面推出来的那个式子,闵和合并恰好能对的上,对于其它的归并方式都对不上,所以是对的。
QOJ 5096 千百
利用方差(找不变量后转化操作和目标),数圈(对于环形看成无限循环)这两个题的技巧。现在需要交换不同类使得能够排序。
QOJ 7899 Say Hello to the Future【口胡】
表示将 划分成若干段。处理 dp 之间的转移也可以考虑 cdq 分治,假设中间向右延伸 ,向左延伸 ,那么需要 ,这里 是从中间往右往左的前缀 。那么枚举 之后相当于每次激活一个 ,查询后缀和,这样单次询问能做到 。
对于原问题,先处理出前后缀的答案,在中点分治的时候需要对其中每个 统计包含 的区间 跨过分治中心时 的和。
假定 ,如果 不是后缀 max,那么要统计 ,从大到小扫 即可;如果 是后缀 max,假设它再往前(这里是原序列再往前)比它大的位置是 ,那么在 还是 ,在 的地方是 ,这里 是次大值。
总之分类讨论之后都能扫描线 + 树状数组解决(其实就是二维偏序)。
QOJ1289 A + B Problem
假定 ,将 填到 。
- 存在一种最优方案,使得 的剩余长度始终 的长度。
当 和 剩余长度相等时,接下来的数放哪里是等价的,钦定给 即可。
- 假如开头是 0,那么填到 更优。
也就是要证明对于任意的 , 是 一定优于 。现在说明对于后者的任意方案,总存在一个前者的方案不劣于它。如果后者的第一个数给了 ,那么前者给 ,都递归到了 的问题,前者不会更小;如果后者第一个数给了 ,前者也给 ,归纳到了证明 永远不会比 劣,归纳的终点就是 不会比 劣。
推论:在 填完之前, 只会扔给 。
于是去枚举 的末尾是 ,那么 就是 个 1 再拼上 , 就是 种删去 个 1 剩下的最大值,贪心一定是最后 个 1,此时考虑 从小往大枚举的过程中,如果扫过去一个 1 那么答案不变,如果扫过去一个 0,那么 会增加一个数, 会删掉倒数的 1 再添加一个 0,那么发现此时 的增加量会越来越小, 的减少量会越来越大,只需要找到最优的那个前缀即可,时间复杂度是线性的。
QOJ6349 Is This FFT?
观察 Kruscal 重构树,需要儿子的拓扑序小于父亲,然后每个点上会挂着若干个点(也就是合并两个集合时新加进去的其他边),需要当前点拓扑序小于挂着的这些点,那么就可以用 SAO 那个容斥,令 表示是 Kruskal 条边连起来了,重构树上带上容斥反向的那些边 size 为 ,带容斥系数的方案和。
转移写出来容易做到 ,发现只需要记录点值,最后统一 idft,这样就是 (最后这部分很口胡,还是得写出来再对着优化)。
LOJ 4133【口胡】
倒着做,遇到一个查询就在这个点上插入这个查询,遇到一个染色就在邻域中有查询的点都回答掉。那么只需要支持单点颜色黑白修改,查询某个点最近的黑点。LCT 直接做就行 /fn。
pakencamp_2022_day2_h Habatu
相当于最初为 ,找最小的边切成 ,递归到权值和较大的那个儿子,最终递归到的 就是答案。考虑向下跳的过程,想要一次能跳很多,每次权值除 2,这样只会跳 log 次,遇到这种按权值和切分的问题可能还是要考虑带权中点这种东西。
考虑找到尽可能长的前缀 使得 ,找到最长的后缀 使得 ,中间的一段是 ,这里 是当前区间 的总和。由于 的总和大于 ,所以如果切在 中,那么留下来的一定是拥有 的那一边,于是可以考虑 中的最小的边 ,向左找到 中第一条 的边,向右找到 中第一条 的边,那么切 前一定是在左右两侧不断切直到剩下这两条边中间的这一段,再切一步 。
现在分析最劣情况,这里最劣情况是 为橙色边,这样子删掉的点是 以及 的最左侧点,那么权值和最劣乘 ,这里绿色边也属于《切完之后一定留下的是含 的那一段》的范畴之内的,那么总的复杂度就是 ,一共切 轮,每次需要线段树上二分。
P10717 【MX-X1-T5】「KDOI-05」简单的树上问题【口胡】
三进制数表示状态, 表示没有, 表示有并且没有封闭, 表示有并且封闭
- 假设 的第 个属性是 ,需要所有儿子的第 个属性为 ;
- :每个儿子可以是 可以 ,至少有一个;
- :《只有一个儿子 其余都是 》或者《至少两个 其余全是 》
那么在把儿子们依次合并的过程中,四进制数记录每一个属性的状态:
- 表示儿子们的这个属性均为
- 表示只有一个儿子的属性为 其余全为
- 表示只有一个儿子的属性为 其余全为
- 表示至少有两个儿子的属性为 其余全为
那么在每一位上就是这样的变化:
- ;
- ;
- ;
枚举 每一位是怎么转移的,就能得到一个 的做法。
下标进行位运算的卷积,看着就很想魔改 fwt 对吧!首先把四进制和三进制改成四进制和四进制运算,可以想到将儿子 的一些 变成 ,含义是不断合并的过程中这一位最后要变成 ,然后发现算多的部分就是这一位为实际为 ,所以将转移改写成下面这种:
- ;
- ;
- ;
然后实际上这里 是记录了一个只看 的类似高维前缀和的东西,所以做一下高维前缀差分还原即可。这样复杂度就是 。
[NOI2024 模拟赛 Day 8] 括号序列
给定 和正整数序列 ,对每个 可以选择交换 ,最大化 。
对每个 数 的 个数为 , 个数为 ,那么 就是答案,此时考虑从大到小枚举 ,这样子 是定值,所以相当于最小化 ,相当于都扔到数轴上,每一对数可以决定一个 +1 一个 -1,最小化后缀和的平方和。
还是考虑弱化问题,考虑下界是否能达到,相当于把所有数扔到数轴上,强制相邻 权值不同, 权值不同 ...... 额外的,还要强制 不同。如果不同就连一条边,二染色即可,每个点度数都是 而每个连通块大小一定是偶数,所以可以二染色。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?