秋季做题记录
08.31
#8268. Tycho
每个点要么直接走要么等到最近的 \(kp\) 时刻走。你设计 \(f(i)\) 表示走到 \(i\) 等到一个 \(kp\) 的最小代价,转移枚举上一个等到 \(kp\) 时刻的位置,有转移:
把除法取整拆成两元素各自取整的结果加一个按 \(v\bmod p\) 大小关系产生的 \(O(1)\) 的差量,容易权值线段树实现。需要特殊处理一下到终点的贡献因为无需等待
P3059 [USACO12NOV] Concurrently Balanced Strings G
对 \(r\) 扫描线,考虑描述合法的 \(l\)。记 \(s\) 为前缀和,则需 \(s_l=s_r\) 且 \(\forall i\in [l,r],s_l\le s_i\)。对于后者,你对每个 \(l\) 找到首个不符合条件的 \(r\) 即可。对于前者,直接哈希一列的信息即可,开一个 map 计数就做完了。
P5305 [GXOI/GZOI2019] 旧词
一个经典套路是维护每个点与父亲的价值差分,然后 LCA 信息就可以到根链求和、到根链加维护。
#7943. LIS on Grid
考虑 Dilworth 定理。将二维偏序视作反链,则偏序关系为 \(r\le r\lor c\le c\),一条链可以描述为从一个点开始不断向右走或者向上走得到的一条路径,则只需满足原图可以被划分为 \(k\) 条链,充要条件为:
考虑证明必要性。每条链初始显然都在最下面,则每条链至多上升 \(n-k\) 次,总次数即 \(k(n-k)\),故超过该值必然非法。充分性容易按上文构造证明。不妨将不足 \(k\) 的 \(a\) 视作 \(k\) 构造最后任选多出来的删掉即可。
CF193D Two Segments
显然关心值域区间,对 \(r\) 扫描线。考虑对每个 \(l\) 维护什么,实际上只需要维护当前 \([l,r]\) 所分段数即可,因为你插入一个点对段数的影响只与其前后两个元素有关,所以变化量是 \(O(1)\) 的,可以直接区间修改,放上线段树即可。
所求即为段数为 \(1\) 或 \(2\) 的区间数,注意到段数不小于 \(1\),故只需维护最小值和次小值及其个数即可。注意最后减去 \(n\) 个单点。
#5357. 芒果冰加了空气
可以视作删点,不同连通块的点删除顺序无影响。你发现对 \(x\) 的一个儿子 \(y\),\(y\) 删除后其子树不影响,故只关心 \(y\) 子树内有几个与 \(y\) 同连通块的比 \(y\) 先删,容易设计 \(f(i,j)\) 表示 \(i\) 子树中有 \(j\) 个这样的点比 \(i\) 先删的方案数,转移预先做一个前缀和即可类树上背包 \(O(n^2)\)。
#12035. 高维树
你发现一个维度至多作用于一条链。不能复用。故而我们考虑最小化这样的链数,给叶子两两匹配即可。
然而这样并不完备,注意到若两条链无交,二者距离是不正确的,需要钦定所有链有交。考虑找到关于叶子数的带权重心,然后再给不同子树内的叶子两两匹配,如果有奇数个叶子最后一个从根连过去即可,这样所有链交于根,同时链数最小。
P17197 [KOI 2026 #2] 删除局部最小值
考虑对每个点找到两侧首个不小于他的,若没有或与其相等,则当前点删不了;否则,把他们之间的点删完之后,下一轮就删当前点。而他们之间的点,实际上只需要求区间 \(\max\),单调栈处理即可。
考虑区间查询,你发现如果区间不包含两侧首个不小于他的点任一个,这个点就删不了,否则其贡献无变化。故而一个点贡献仅当左右端点与时间各满足一个条件,形如一个三维偏序,直接上 CDQ 即可。
09.01
[MXBZ2026 R1] 双网通行
事实上,距离不超过 \(3\),假定起点为白点:自己距离为 \(0\);邻点和白点点距离为 \(1\);非起点邻点并有白色邻点的黑点距离为 \(2\);剩余黑点距离为 \(3\)。
[MXBZ2026 R1] 栏目排列
将连续段的贡献放在起始位置处理,则前一位为 \(0\) 当前位为 \(1\) 的就能产生 \(1\) 的贡献,容易 \(m^2n\) 预处理出各方法贡献,直接状压 \(f(S,x)\) 表示放了 \(S\) 中的元素最后一个放的 \(x\) 即可,复杂度 \(O(2^mm^2)\)。
[MXBZ2026 R1] 序列消除
进行一次删除后,剩余各段是相互独立的。容易考虑区间 DP 状物,你注意到对于每个右端点 \(r\),有效的左端点只有某个颜色在其之前首次出现的位置以及整个序列开头,因此只有 \(O(nv)\) 个有效区间,故考虑设计 \(f(r,x)\) 表示右端点为 \(r\) 前一个被删的颜色为 \(x\) 的方案数。转移枚举删除颜色 \(y\),要求 \(y\) 出现过,我们只需剥离最右边一段即可,最右边一段的方案数为 \(f(r,y)\),而前面的部分形如“当前右端点颜色已删除,上一个被删除的颜色为 \(y\)”的贡献,不妨再设计一个 \(g(r,x)\) 表示它。
按远近顺序处理各颜色即可。转移 \(f(r,x)\) 时特殊处理删除右端点颜色 \(y\) 的情况,此时 \(f\) 和 \(g\) 的转移是相同的,如果左端点之后仍有颜色 \(y\),系数就是 \(g(la_{r-1}(y),x)f(r-1,y)\),否则就是 \(f(r-1,x)\)。其余情况就只转移 \(f\),系数为 \(g(la_{r}(y),x)f(r,y)\)。复杂度 \(O(nv\log v+nv^2)\)。
考虑区间查询,依旧枚举首次删除的颜色,你发现只有左右两个端点是散的,中间形如一个整段,你对各左端点也跑一遍上述过程,然后中间部分前缀和一下就做完了。查询复杂度 \(O(qv\log V)\),这个 \(\log\) 是逆元。
[MXBZ2026 R1] 停机检查 / #1192. Halting Problem
一个关键观察是,称 \(x=a_i\) 情况下走的边为关键边,则每条关键边只会被走至多一次,否则必然成环,因为走完这条边 \(x\) 是定值,走多次的话情况完全相同。
因此我们只需要对走完每条关键边以及初始情况共 \(n+1\) 种情况,快速求出其走到的下一个关键边,或者走到 \(n+1\),或者走不出去,以及所用步数。非关键边形成的是一个基环树森林,如果一个询问的终点不在环上,容易在树上进行一次搜索处理出来,维护树上到根前缀和 \(dt\),则要求 \(a_y+dt_y=val+dt_x\),开一个 map<vec<int>> 动态维护即可。
考虑在环上的情况,不妨先走到一个钦定的起点,维护走一圈的价值和 \(S\) 与起点到每个点的前缀和 \(s_i\),则第 \(k\) 圈走到第 \(i\) 点时的 \(x=val+kS+s_i\),环上步数为 \(i+km\),\(m\) 为环长。那么走到一个点恰为其 \(a_i\) 所需圈数为 \(k_i=\frac{a_i-s_i-val}{S}\),若 \(k_i<0\lor |S|\nmid a_i-s_i-val\) 则永远走不到。因而要求 \(a_i-s_i\equiv val\pmod {|S|}\),你同样对每个余数 \(r\) 开一个 vec<int> 维护 \(\frac{a_i-s_i-r}{|S|}\),然后对每个 \(val\) 在里面二分首个不小于 \(\frac{val-r}{|S|}\) 的即可。\(|S|=0\) 容易特殊处理。
P17019 [ROI 2026 Day1] 泰莫利亚的调查
也就是选若干条完全不交向上链最大化链长之和。
第一次显然选最长链即可。之后每次,要么选一个新链,要么断开原来链上一条边然后从父亲点向外重新连边。对于前者显然必然从原来链上一个点选一个叶子开始往下连。显然别的方案均不优,否则之前的操作可以调整得更优。
考虑关心选择的链上点,把所有可选点的价值扔到堆里取最大值即可,显然单点总影响量是 \(O(n)\) 的。考虑快速维护一个点更新后的答案,其子节点 \(i\) 贡献形如 \(\max(0,e_i-x)+v_i\),\(e_i\) 为 \(i\) 父边边权,\(v_i\) 为 \(i\) 往下选的答案,那你对每个点开两个堆分别维护 \(e_i+v_i\) 和 \(v_i\) 即可。
09.02
[MXBZ2026 R2] 披萨晚宴 / #18248. Ovenmasters
先把前 \(m\) 个按给定顺序放上,然后给所有桌子按初始权值升序排序,由于插入操作的性质,任何时刻桌子当前的权值在该顺序下均升序。
我们考虑将“\(a\) 必须在 \(b\) 之后放”的限制连边 \(b\to a\) 然后跑拓扑状物,最小化字典序开一个小根堆每次选能选的最小值即可。考虑有哪些连边,先考虑出现过的,首先同一张桌子上的披萨两两相邻连边,若上面的比下面的小显然非法,故而同一张桌子上的所有披萨也是单增的。此外,要求这个披萨不能放到后一张桌子,你在后一张桌子上二分首个比他大的然后连边即可,不存在即非法。
然后考虑不在桌子上的,要求他插入的时刻局面内所有桌子上的披萨都比他大,你在每张桌子上找到首个比他大的连边即可。但这样边数会达到 \(O(n^2)\) 级别。考虑优化,你给不在桌子上的升序排序,然后顺序考虑,假如上一个是 \(i\) 这一个是 \(j\),先处理完 \(i\),然后直接连边 \(i\to j\) 因为要最小化字典序所以没有影响,然后枚举 \((i,j)\) 内的数,把他在桌子上的后一个披萨和 \(j\) 连边,如果没有就非法,这样就是 \(O(n)\) 的了。
最终复杂度 \(O(n\log n)\)。
[MXBZ2026 R2] 分层编辑器 / #13034. Editor
需要对每个加入点找到,他之前最近的激活状态下且等级比他小的点。
我们考虑对每个点维护,若其处于激活状态,左侧最近的激活状态下等级比他小的点。这样加入点 \(i\),先看 \(i-1\) 等级是否比他小,是则直接连边,否则在链上倍增跳即可。
考虑维护这个东西,首先找到 \(i\) 撤销的操作 \(x\),则 \((x,i)\) 中没有等级更小且被激活的点,那么既然 \(x\) 原处于激活状态,\(x-1\) 必然处于激活状态,你从 \(x-1\) 开始倍增跳到首个比 \(i\) 等级小的即可,倍增容易动态维护。
[MXBZ2026 R2] 画布 / #5242. Płótno [B]
关心值域序列,扫描线扫 \(r\),动态维护所有 \(l\) 的连续段个数,然后维护一下区间前 \(k\) 小即可,容易线段树实现。
考虑更新,插入位置对于连续段个数的影响其实只在于其上(或下)、左、右三个邻点原先的存在情况和连通情况,若存在或连通必然是在一个前缀左端点,故而可以做成常数次区间加。
存在是平凡的,考虑判定连通。形如对每一个右端点 \(r\),常数次询问,每次给定两个点,问使他们连通的最大左端点。你发现行数只有 \(2\),破环成链,相当于查询一个区间左右端点连通的最大左端点值,你对每个区间维护左端点上、下和右端点上、下四种情况的答案,合并直接 \(O(2^3)\) 枚举两个区间的端点情况,要求中间拼合部分一致,容易线段树实现。
[MXBZ2026 R2] 快速旋转 / #9963. Express Rotations
按值域从大到小考虑。显然如果队首是最大值能删就删不劣,否则要转动序列,那显然只会往左走一段再往右走,或往右走一段再往左走,其余的方案是不优的。
对于值 \(v\),设其所有位置为 \(p_1\sim p_m\),我们考虑对每个 \(p_i\) 维护出 \(v\) 最后一个删的位置为 \(p_i\) 的最小代价 \(f_e(i)\),那么首次转到 \(p_i\) 的最小代价容易由 \(v+1\) 的 \(f_e\) 单调队列得到,记作 \(f_b(i)\)。
破环成链,用 BIT 动态维护仍在序列上的位置区间和,我们预先将 \(v\) 的部分删去,对每个 \(v\) 位置存储其后一段的价值,前缀和为 \(s\),那么从 \(i\) 开始到 \(j\) 结束的两种走法代价分别为:
容易分离 \(i,j\),那么每个 \(j\) 只需要选取 \((j,j+m)\) 内的 \(i\) 的最小代价即可,再写两个单调队列就做完了。
P14284 [ICPC 2025 WF] Delivery Service
显然考虑把每个点拆成两个状态然后直接并查集,但显然会算重。
我们不妨记 \(S_i\) 为连通块 \(i\) 内的去重后点集,可以直接启发式合并,那么答案的一部分是 \(\sum_i{|S_i|\choose 2}\)。但还是会算重,存在一对点在两个不同连通块连通两次的情况,也就是要减去 \(\sum_{i<j}{|S_i\cap S_j|\choose 2}\)。
考虑如何维护后者,你考虑一个点只会出现两次,因此交集大小之和是 \(O(n)\) 的,同时一个集合与其他集合的交集大小之和不超过集合内元素个数,你暴力地维护三元组 \((i,j,c)\) 表示 \(S_i\cap S_j=c\),考虑合并 \(S_i\gets S_j\),对于 \((i,k,c_i)\) 和 \((j,k,c_j)\),你发现合并之后就是 \((i,k,c_i+c_j)\),因为一个元素不可能出现三次。\(i\) 没有的 \((k,c)\) 直接转接给 \(i\) 即可,\(k=j\) 就直接删了。
09.03
CF547D Mike and Fish
容易把网格图转为二分图,将红色视为行连列,蓝色视为列连行,则要求给边定向使得所有点入度与出度之差不超过 \(1\),你对每个连通块去找一条欧拉路径即可。
但并不完善,因为存在欧拉路径仅当图中度数为奇数的点不超过 \(2\) 个。注意到度数为奇数的点必然有偶数个,直接将他们和一个虚点连边即可,这样所有点度数均为偶数,然后跑欧拉回路就行了,欧拉回路中每个点出入度相等,把连向虚点的边去掉仍满足度数差不超过 \(1\)。
P15869 【MX-X26-T5】「Cfz Round 7」anybody can finds love (expect you)
首先是否存在欧拉回路是好判的,考虑保证重边不相邻出现,你尝试给每个点的所有边两两配对满足配对边邻点不同,只要不存在绝对众数即可。
给配对的边放一组,那么每组的边都形成一个环。你考虑合并一个交点的两个环,设其在两环上的边分别为 \(a\ne b,c\ne d\),则 \(a\ne c\land b\ne d\) 和 \(a\ne d\land b\ne c\) 必然有一个成立,选成立的一种方案直接插入即可,容易用链表维护序列。
AGC018F Two Trees
一个关键性质是,由于子树和为 \(\pm1\) 均为奇数,故有解的一个必要条件是每个点在两棵子树内的儿子数量奇偶性相同。不妨给两个根连一条边,那么就可以转化为度数的奇偶性。
然后一个非常神仙的构造是,你将度数为奇数的点在两棵树中的对应点连非树边,得到一个所有度数均为偶数的图,跑欧拉回路,原偶数度数节点权值设做 \(0\),否则若非树边从 A 到 B 就设做 \(1\),从 B 到 A 就设做 \(-1\)。
考虑证明,你将欧拉回路拆分成若干简单环,对于一个点 \(x\),不妨考察 A 树,若一个环在 A 树上的部分完全在其子树内,则一去一回两条非树边的权值抵消了。否则,若一个环经过了 \(x\) 的父边,则会给 \(x\) 贡献 \(\pm 1\),同时由于父边只能被经过一次,这样的贡献必然只有一次,故符合条件。
对于根节点,我们去掉之前额外连的那条边,将之替换为一个虚根作为两个根节点的父亲,因而两个根同样符合条件,而虚根的权值无需在意,故符合条件。
P3275 [SCOI2011] 糖果
差分约束板子。你直接 SPFA 跑最长路,加一个入队次数超过 \(2e7\) 就退出,可以卡过。考虑正解,注意到边权只有 \(0/1\),你先把为 \(0\) 的连了跑一遍 tarjan,则每个 SCC 内部权值相同,然后再连为 \(1\) 的边拓扑做即可。
P11095 [ROI 2021] 旅行 (Day 2)
升序枚举边权 \(v\),则路径最大值已知,考虑加入边权为 \(v\) 的边。考虑当前局面,对于每个环,无论起点终点是什么都可以贡献其中最小边权,可以直接缩点,剩余部分形如一棵树。
那么有几种情况,如果在一个边双内部,没有作用;产生了一个新的边双,可以直接暴力缩点,同时更新其中的答案,总合并次数在 \(O(n)\);连通了两个连通块,貌似有点繁琐,考虑可以预先把 MST 跑出来,然后在上面更新信息。
具体地,我们对 MST 维护两个信息:到根路径最小值以及答案。路径最小值是容易更新的,你产生新边双时统计其中新的最小边权,然后对边双内深度最小的点进行子树更新即可;更新答案时,我们假定树上所有边均已加入,则同样只需考虑产生新边双的影响,那么有贡献仅当最小值为边双内最值,否则加入当前边没有作用,故而可以直接用边双内最小值加上当前边权更新子树答案,然后当每个点首次与根连通时刷新单点信息即可。
P4630 [APIO2018] 铁人两项
考虑描述一组合法三元组。首先三者必须连通,其次不存在点 \(x\),使得删除 \(x\) 后,\(s,f\) 同时与 \(c\) 不连通。你发现这是充要的。
考虑建出圆方树,枚举 \(c\) 所在圆点,第一种是 \(s,f\) 来自 \(c\) 的不同子树,容易处理,第二种是 \(s,f\) 在同一个点双的不同点交汇,然后走到 \(c\),则 \(c\) 必须为点双上点,可以转而枚举交汇点双方点做。
P6378 [PA 2010] Riddle
2-sat 板子,对于一个部分的限制你做一个前后缀虚点优化即可实现至多选一个,至少选一个的限制无需考虑,因为如果有部分没有选局面合法,你随便选一个局面仍合法。
P5332 [JSOI2019] 精准预测
首先肯定有一个暴力做法,你把 \(2nT\) 个状态全部建出来然后跑 2-sat,同一个人,之前死了后面就一直死,后面活着之前就一直活,然后给定的预测是平凡的,记得反情况要连反边,查询的话你就看 \(i\) 在 \(T+1\) 时刻活着会导致几个人在 \(T+1\) 时刻必死,特别的若会推出自己必死那 \(i\) 就必死,自己答案为 \(0\) 并且其他所有点要算上 \(i\) 的贡献。
考虑把时间轴压缩掉。各个操作均只在当前时刻有效,那么对于一次操作,我们只显式激活这次操作的两个点各自相关的时刻即可,这样点数就在 \(O(n+m)\)。
考虑求答案,你发现是个 DAG 可达性计数,直接 bitset 空间爆了,但不 bitset 不太可能,于是给目标点分块就好了。记块长为 \(B\),消耗空间在 \(4(n+m)\frac{B}{8}\text{byte}\),时间复杂度为 \(O(\frac{(n+m)^2}{B}+(n+m)\frac{n}{w})\),取 \(B=10^4\) 即可。
09.04
#10706. Red-Blue MST
首先容易先对红蓝边分别跑一棵 MST 出来,则不在 MST 上的边必然没用。
剩下的红边有两种,一种是必须加,这个也容易处理出来,后文忽略掉,考虑另一种,他要加入就要替换掉原来的一条蓝边。
考虑一个选定的红边边集,求他产生的生成树。我们先得到蓝边的 MST,然后按边权升序枚举红边,选定路径上最大的剩余蓝边替换。这个过程还可以表示为,将蓝边和红边分别升序排序,那么对一条红边 \((u,v)\),我们考虑描述他替换掉的蓝边,先将他之前的红边全部加入,然后找到首个蓝边前缀使得 \(u,v\) 连通,那条边就是他替换掉的,显然每个红边对应的蓝边均不同,容易反证,有两条红边“删掉这条蓝边两端点就不连通”,然而边权更小的红边相当于顶替了这条蓝边,因此边权更大的红边删掉这条蓝边没有影响,矛盾。
那么,在我们贪心地升序选红边的过程中,每个红边对应的蓝边是一定的,否则不优。考虑反证,假如这条红边对应蓝边发生变化,显然只会边权变得更大,那么这条蓝边原先必然对应了边权更小的另一条红边,把它调整过来不劣。
因此存在一个暴力是对每条红边去二分他对应的蓝边。这个过程是可以整体二分的,我们先把 \([1,mid]\) 的蓝边升序加入,然后再升序尝试加入当前的所有红边,那么在树上的红边他替换掉的蓝边就在 \((mid,r]\) 内,将这些红边记作 \(Q_r\),不在树上的红边他替换掉的蓝边就在 \([l,mid]\) 内,将这些红边记作 \(Q_l\)。
对于 \(Q_r\) 中的红边,你本应关心 \(Q_l\) 中边权比他小的边,然而你加入他之前的红边之后,他的两个端点仍不连通,而 \(Q_l\) 中的红边两个端点在加入 \([1,mid]\) 的蓝边后已经连通了,所以加不加 \(Q_l\) 中的红边对 \(Q_r\) 中的边端点连通性判定无影响,于是可以不管。
对于 \(Q_l\) 中的红边,你本应关心 \(Q_r\) 中边权比他小的边,然而 \(Q_r\) 中边权比他大的边的两个端点,在处理这条红边的时刻尚未连通,而这条红边的两个端点在当时已经连通了,因此加入这类边对这条红边端点连通性判定无影响,于是我们可以在向左递归之前直接把 \(Q_r\) 中的所有红边先加入。
P6643 [CCO 2020] Mountains and Valleys
如果不走非树边,代价就是 \(2(n-1)-\mathrm{diam}\)。假如走一条非树边,记其端点为 \(u,v\),边权为 \(w\),若起点和终点分别为 \(s,t\),代价为:
而你走一条非树边,就要求其树上路径长度超过边权,则 \(\mathrm{diam}>\frac{n}{3}\),那你倘若走两条非树边,因为每个点至少被经过一次,代价大于 \(n-3+\frac{2}{3}n=\frac{5}{3}n-3\),而你不走非树边的代价不大于 \(\frac{5}{3}n-2\),你发现不劣,因此非树边只会走至多一条。
\(\max\) 很不好看,我们分讨有交无交两种情况把他拆了。枚举 \((u,v,w)\),则我们要求最大的 \(\mathrm{dis}(s,t)-2|\mathrm{path}(s,t)\cap \mathrm{path}(u,v)|\),相当于给 \(u,v\) 路径上的边权设做 \(-1\) 然后求直径,于是有一个 \(O(nm)\) 的做法。
考虑点分治,你只处理经过分治中心的 \((u,v,w)\)。你对每个点处理出,假设他到分治中心的路径边权为 \(-1\),在他所在分治中心儿子子树中选一条向上链、一整条链有交或无交的答案,显然是可以 \(O(n)\) 做的。注意到块大小不超过 \(\frac{n}{3}\) 无需考虑,故只会计算不超过 \(3\) 次。然后就能做到理论 \(O(n+m)\)。
#7980. 区间切割
先考虑全局操作。倘若 \(x\) 为随机排列,则每个区间期望被操作 \(O(\log n)\) 次,我们只需考虑快速找出影响各个区间的操作即可。我们记录下每个点的操作时刻,枚举区间,每次取区间 \(\min\) 位置的操作即可。
倘若 \(x\) 非随机排列呢。非常牛地,我们将一个区间三等分为 \(l,ml,mr,r\),则落在 \([l,ml)\cup(mr,r]\) 内的操作,必然只会修改自己一侧的端点,于是我们可以只关心落在 \([ml,mr]\) 内的操作,这样每次区间长度减为 \(\frac{1}{3}\),也只会执行 \(\log n\) 次。需要查询 \([l,ml)\) 中最大的 \(t\) 小于某时刻的点,线段树上二分即可,右侧同理。
考虑非全局操作,我们扫描线维护每个点的 \(t\) 即可。
09.05
P10357 [PA 2024] Żelki
每种颜色购买数量相同,你考虑每轮每种选一个,然后选若干轮即可。容易 \(O(nm)\) 背包出一轮后各余数的最小花费,然后跑一个同余最短路,\(|V|=m,|E|=nm\),你跑不带堆优化的 dijkstra 即可做到 \(O(m^2+nm)\)。
P13534 [OOI 2023] The way home / 回家的路
你考虑在一条路径上,你必然只会在各个前缀最大值处表演。因此考虑只关心各前缀最大值,先 \(O(n^3)\) 预处理出两两距离,然后你发现你需要关心到这里的操作次数和当前剩余量。你考虑,如果可以不表演直接到这里,那不表演显然不劣,否则剩余量必然小于上一次表演的 \(w\),而上一次表演的 \(w\) 比当前 \(w\) 更小,因此你在这里额外表演一次是不劣的,故而你只需对每个点跑出最小表演次数,在此基础上再去最大化剩余量即可。
AGC034D Manhattan Max Matching
容易考虑二分图跑费用流,但直接建模边数在 \(O(n^2)\) 很不好过。你考虑曼哈顿距离两个绝对值都是可以拆的,拆出来四种情况,你开四个虚点表示,然后将 \(2n\) 个点和这四个虚点连边即可,然后直接费用流就过了。
AGC056C 01 Balanced
考虑前缀和后差分约束,但是直接做有点炸。考虑将 \(0\) 视作 \(-1\),这样区间 \(0,1\) 相等可以视作 \(s_r=s_{l-1}\),可以直接合并,约束相邻点只能做到约束差绝对值不超过 \(1\),然而不会出现差为 \(0\) 的情况,因为你合并的两个点必然同奇偶,合并完相邻点连边只会在奇偶点之间,也就是二分图,边权又都是 \(1\),因而两侧距离奇偶性必然不同,不会相等。最小化字典序从 \(0\) 开始跑最长路即可。
ARC076F Exhausted?
显然是要求人和椅子的最大匹配。考虑霍尔定理,对于一个左部点集合 \(S\),\(|N(S)|\) 即为 \(\min(m,\max_{i\in S}l_i+m-\min_{i\in S}r_i+1)\)。我们将所有左部点按 \(l\) 升序排序然后扫描线,则 \(\max l_i\) 已知,我们希望选若干点并对一个点数尽可能最大化 \(\min r_i\),对 \(r\) 开一个权值线段树即可。
CF1361E James and the Chase
先随便找到一个好点,然后拉出一棵 DFS 树,若一个点子树内有两个返祖边它必然不是好点,否则它是好点当且仅当那条返祖边指向的点是好点。找初始好点的话直接随几个就行,随不到就当好点数量不够。
P13592 [NWRRC 2023] Loops
对一个环,我们将其 \(6\) 条偏序关系连出来,你发现必然存在一对对边同向,那么必然存在摆放方案,使得每个点先向右连边,同时第一列上的点向下连边。你这么连出来,然后逐个确定剩下的边,你发现必然不会成环,故而直接跑拓扑即可。
P11812 [PA 2015] 精确打击 / Kontrmanifestacja
见微近做题记录。
09.07
P13358 [GDCPC 2024] 小班课
容易考虑一个拆点然后是一个匹配状物。但是每个学生有一个意向度排列。有一个想法是,若一个学生当前意向度最高的课程不是他的最终匹配,那你大可以把他往后放,直到他意向度最高的课程恰为他的匹配,就给他放上。
这样能构造方案当且仅当,没有两个点匹配出顺序交错的情况。直接调整并不好做,你考虑只关心每个时刻当前点 \(x\) 意向最高的有余量的课程,若其的一个匹配点是 \(y\),我们连边 \(x\to y\),这样能得到一棵基环树,那么环上的点必然可以匹配上自己意向最高的点,就可以先把环上的点做掉,然后就是子问题。因此答案是可以直接取到最大匹配的,显然这是上界。
2061G - Kevin and Teams
先考虑如何确定 \(k\)。你考虑对于一个已知匹配的图,你把所有已匹配点连成完全图显然是不劣的,这样在补图中他们之间没有边。那剩下的未匹配点呢,你选一个加入之前的团,剩下的不连边,感性理解这样不劣。
记原图匹配点数为 \(x\),则团大小为 \(2x+1\),易知反图最大匹配为 \(\min(n-2x-1,2x+1+\max(0,\lfloor\frac{n-4x-2}{2}\rfloor))\)。对一个大小为 \(3k+1\) 的图,你直接取 \(x=k\) 即可达到 \(k\) 的答案,感性理解这样两侧答案均衡最优。由此推得,一个 \(n\) 个点的图答案为 \(\lfloor\frac{n+1}{3}\rfloor\)。
考虑查询 \(n\) 次并构造。你考虑维护一个同色的链,用链尾和一个新点查询,若同色就加入链,否则你就把链尾和链尾前一个、链尾和这个新点分别加入两个匹配,同时删除链尾和链尾前一个点。这样消耗三个点即可兑成一组匹配,最后链还有剩得就贪心匹配加入即可。
AGC036D Negative Cycle
考虑差分约束。初始 \(n-1\) 条边即可描述为 \(a_i\ge a_{i+1}\)。
对一条 \(x\to y\) 的负边,含义为 \(a_y\le a_x-1\),那么若其保留,则对于 \(x'\le x,y'\ge y\) 的所有 \(x'\to y'\) 均可以保留。同理,对一条 \(y\to x\) 的正边,含义为 \(a_x\le a_y+1\),则对于 \(x\le x'<y'\le y\) 的所有 \(y'\to x'\) 均可以保留。
你注意到约束下差分值是很小的,我们转而关心 \(\delta_i=a_{i-1}-a_i\),则 \(\delta_i\ge 0\),\(x\to y\) 约束写作 \(\sum_{i=x+1}^y\delta_i\ge 1\),\(y\to x\) 约束写作 \(\sum_{i=x+1}^y\delta_i\le 1\)。那么显然钦定 \(\delta_i\in\{0,1\}\) 即可。
对保留情况构造序列很不好做,我们转而对序列求最大保留价值。首先完全被包含在 \(0\) 连通块内的负边均需删除,然后跨越了两个 \(1\) 的正边亦需删除。因此我们只需对每个右端点关心前两个 \(1\) 的位置即可,容易 \(O(n^3)\) DP。
#7872. 崩坏天际线
我们考虑计算 \([l,r]\to [x,y]\) 的概率,首先 \([x,y]\) 内部不得有崩坏操作。否则,你考虑 \((l,x]\) 中所有的时间后缀 \(\max\) 位置,他们均需选择右侧,\([y,r)\) 中同理。
那么容易离线下来,倒序处理,操作二更新单点信息,操作一建一个笛卡尔树然后直接计算答案,复杂度 \(O(n^2)\),\(8\) 秒优势在我。
P16997 【MX-S15-T3】「DLESS-5」旅游定价
显然所求为 \(n\max\{\sum p+\sum q\}\)。
考虑固定 \(q\),则 \(p_i=\min_j|x_i-a_j|-q_j\)。将之一般化,设 \(f(x)=\min_j|x-a_j|-q_j\),则 \(p_i=\max_{x\in S_i}f(x)\)。
尝试发掘 \(f\) 的性质,注意到对于一个 \(j\) 是一个绝对值加一个常数,你把图像画出来,则一个 \(j\) 若有作用范围,必然为一段连续区间,同时你关心峰值 \(x=a_j\),你发现其必然由 \(j\) 作用得到,否则你增大 \(q_j\) 不劣。也就是说,\(f(a_j)=-q_j\),则所求即为 \(\sum_i \max_{x\in S_i}f(x)-\sum_j f(a_j)\)。
\(f\) 函数限制还是太多了,非常牛地,我们考虑直接把他放缩掉。我们考虑求一个 \(g(x)\) 满足 \(f(a_j)=g(a_j)\land g(x)\le f(x)\),那么可以直接转而求 \(\max_g\sum_i\max_{x\in S_i} g(x)-\sum_jg(a_j)\)。之所以如此,是因为 \(g\) 函数的限制可以直接写作 \(|g(i)-g(i-1)|\le 1\),这样令 \(f(a_j)\gets g(a_j)\) 后必然有 \(f(x)\ge g(x)\)。
转而关心 \(\delta(i)=g(i)-g(i-1)\in\{-1,0,1\}\),将 \(g\) 的贡献拆到 \(\delta\) 上,假定我们已然确定了 \(x\),则 \(\delta(k)\) 的转移系数为 \(\alpha_k=\sum[x_i\ge k]-\sum[a_j\ge k]\)。既然我们要求最大值,那么让 \(\alpha_k\delta(k)\gets |\alpha_k|\) 即可,故可以钦定 \(\delta(i)\in\{-1,1\}\)。
我们发现我们还没有使用 \(k\le 15\) 的性质。直接状压前 \(k+1\) 位 \(\delta\) 的正负,然后就能直接算 \(\max_{x\in S_i}g(x)\) 了。复杂度 \(O(nk2^k)\)。
P16309 [ICPC 2023 Jinan R] 图划分 2
容易有一个 \(f(i,j)\) 表示子树 \(i\) 根保留大小 \(j\) 的方案数,转移类树上背包 \(O(n^2)\)。
你注意到有效状态数看上去不多,分析一下。若子树大小小于 \(k\) 必须整个保留,否则至多有 \(n\bmod k\) 个有效状态,而若 \(k\ge \sqrt n\),你考虑子树至多割 \(\frac{siz}{k}\) 次,因而余数实际上也只有不超过 \(\frac{n}{k}\) 种。因此分析下来一个点的状态数在 \(O(\sqrt n)\),树上背包分析出复杂度为 \(O(n\sqrt n)\)。
其实可以优化。你考虑子树大小不超过 \(k\) 的可以全部跳过,同时一个点转移只需考虑子树大小至少为 \(k\) 的儿子,有至少两个大小不小于 \(k\) 的儿子的大小不小于 \(k\) 的儿子数之和是 \(O(\frac{n}{k})\)。因而你直接 NTT 开卷即可做到 \(O(n/k\cdot k\log k)=O(n\log n)\)。更近一步地,我们用暴力枚举有效状态替换 NTT 即可做到 \(O(n)\),分析不动了。
09.08
CF1844G Tree Weights
我们将距离描述为 \(dp_u+dp_v-2dp_{\mathrm{lca}(u,v)}\),则 \(dp_{i+1}=d_i-dp_i+2dp_{\mathrm{lca}(u,v)}\)。推不出什么柿子,感觉只能大力高消。
然后有一个非常牛的 trick。你考虑求各 \(dp_i\bmod 2\) 的值,那么未知量 \(dp_{\mathrm{lca}(i,i+1)}\) 因为前面 \(2\) 的系数就直接消掉了。然后你求 \(dp_i\bmod 4\) 的值,则 \(dp_{i+1}\equiv d_i-dp_i+2(dp_{\mathrm{lca}(i,i+1)}\bmod 2)\pmod 4\),你发现都是已知量。然后你一直做到 \(2^{60}\) 即可。这么牛。
CF1458F Range Diameter Sum
严肃学习树上圆。
考虑分治,对 \([l,m]\) 中的 \(i\) 维护 \([i,m]\) 的邻域信息,对 \((m,r]\) 的 \(i\) 维护 \((m,i]\) 的邻域信息。记 \(i\) 维护的邻域为 \(S_i\),则对于左侧的 \(i\),有 \(S_i\supe S_{i+1}\),对右侧的 \(i\) 有 \(S_i\sube S_{i+1}\)。
因此合并时,你双指针,对每个左侧的 \(i\) 右侧的邻域必然满足,一个前缀被 \(S_i\) 包含,一个后缀包含 \(S_i\),中间有一段与其无后缀关系,显然随 \(i\) 右移这两个指针均单调左移。
那么现在我们需要快速求出,一个点与一个区间内的邻域中心的距离之和,写一个点分树即可。
#837. Giant Penguin
首先 \(m=n-1\) 是平凡的,点分树就行。考虑一般情况。考虑 \(k\) 很小的作用,你发现如果跑一个生成树,那么一个点的各子树之间额外连边不超过 \(k\) 条。暴力地,我们对这 \(O(k)\) 个端点跑一遍 BFS,计算答案时枚举点取最小值即可,算重不影响答案。
CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
考虑描述 DK 串,显然只需满足只有至多一种字符出现了奇数次即可。字符只有 \(22\) 个。考虑状压,一个子树内向上的链个数只有子树大小个,考虑 dsu on tree,合并时你考虑对轻儿子内的所有存在状态,去枚举异或哪一位,然后统计答案,复杂度 \(O(nv\log n)\)。
#6536. 收缩的树
见平凡做题记录(CF1060F)。
P10789 [NOI2024] 登山
注意到有 \(h\ge 0\),因而你向上冲刺一次后,必然会更新上限。所以行程形如,跳到某个点并更新限制,然后下滑到某一点沿途再把限制上提,然后再往上跳,跳到的深度是单减的。故直接设计 \(f(x)\) 表示 \(x\to 1\) 的方案,重定义 \(l,r\) 为能跳到的深度范围,有转移:
从浅到深 DP,但你这个子树转移限制从浅到深很不好维护,考虑从深到浅维护,然后再逐步撤销。考虑 dsu on tree,只维护重链祖先链,那么每个点的贡献相当于一个区间和,做差分就是两个单点加,做完一个点 \(x\) 的子树后要对所有区间右端点对 \(lim_x\) 取 \(\min\),可以直接做成均摊 \(O(1)\) 的单点修改。注意到只有单点操作故而维护答案是容易的,可以直接用一个 map 维护,复杂度 \(O(n\log^2 n)\)。
09.09
P16957 [SCCPC 2026] 那一年的秘密基地
先考虑序列一定时,对每个根求答案。
若根一定,顺序扫描序列,则只需查询子树中有多少元素是之前出现过的,对 DFS 序建 BIT 即可。考虑求所有根的答案,仍顺序扫描序列,你去枚举根所在子树,然后就是一个子树加,再建一棵线段树存答案即可。
考虑修改。只交换相邻两项,则其他点本身不受影响,二者间的答案不受影响,对两个子树修改即可。

浙公网安备 33010602011771号