Exemplary Examples IX

\[\Huge\mathrm{Exemplary\ Examples\ IX} \]

导语见 Exemplary Examples I。

T-211 QOJ18268 26-5-18 S

类似于 T-138,这类题基本的想法就是,先用操作改出来一个特殊的结构,由特殊结构达成最终目标。然后再检查都问一遍,或选某子集问一遍,能得到什么。奇怪的是,虽然步数限制里面有分数,但本题并不是归纳法。

这个题里可以让所有位置互不相同。大概就是说,每个元素去找后面第一个空位,这里最大步数 \(n(n-1)\):每个元素至多绕一圈回来;有一个元素可不用移动。

然后还是不好做。考虑到:如果了解每个元素的位置,则问题解决 (*)。容易想到,在每个位置互不相同的前提下,随意选一个位置移动,造成一个空位,之后每个元素绕一圈,就知道相对空位的位置。超出步数限制,但仍属 \(O(n^2)\) 范围。知道每个元素位置之后,就好解决了。

进行优化。法一:只需了解每个元素的位置,有没有更加容易的办法,无需初始令位置互不相同?可以,先令一号元素绕一圈,得个零一串,若该零一串不存在循环节,则问题解决;反之,令一元素移动至任一个非零位置,即可破坏循环节。令每个元素绕一圈,即可知道它相对一号元素的位置。可通过本题。

法二:在位置互不相同基础上,除了一号元素以外,按编号依次全部操作,就能制造一个空位,还有个“和一号元素重叠”的元素。想要再这样干一次,问题在于“和一元素重叠的元素”没有保持重叠。想要区分“和一元素重叠过”的元素,让它们不动或之类的。发现:在“这样干”的过程中,若上一轮操作元素 \(i\) 的返回值是“重叠过”,且本轮是“不重叠”,则 \(i\) 恰好刚刚离开了一号元素的位置(因为“按编号依次操作”,所以两轮返回值完全一致,才会正常)。但一号元素后边的第一个位置,对后续判断还有作用。所以令 \(i\) 再动一下,并从待考虑集合中删去 \(i\),不参与后续操作。全部做完之后,再令一号元素走两步即可。

T-212 CF436E 26-5-18 B

法一,用反悔贪心。换句话说,扫描 \(i\) 动态维护“想要 \(i\) 颗星星”的答案。考察增量:某关卡从零颗星变成一颗星;某关卡一变二;某关卡一变零,另一关卡零变二;某关卡二变一,另一关卡零变二。可以反悔贪心维护这四种策略。总之就是“选择一个轴,然后不断维护当前最优状态的信息”,就跟普通贪心一样。只不过提供了一些反悔接口而已。

法二,若第一步描述“选了哪些关卡”,则第二步描述肯定是在这些关卡中选择 \(b-a\) 最小的几个玩二星。因此,按照 \(b-a\) 为一个轴排序,那么有一个前缀,只要玩关卡,就一定玩二星;剩下的后缀,只要玩关卡,就一定玩一星。可以枚举前后缀分界线 \(i\)。然后在前缀选择最便宜的 \(j\) 个二星,在后缀选择最便宜的前若干个一星。这大约是 \(O(n^2)\) 的。

现有三个轴:\(i,j\) 还有答案。有时需要考察轴之间的单调性、凸性。对于给定 \(i\),答案显然关于 \(j\) 凸。那我们枚举 \(i\),二分找出最优 \(j\),每次二分 chk 就用数据结构处理一下即可。

T-214 P4426 26-5-25 B

满足 \(m-n\le k\) 的无向图,其中 \(k\) 非常小。那就有两种方法,一种是建立一个生成树,然后关注非树边以及非树边涉及的所有关键点,要么做枚举,要么以关键点建立虚树。第二种就是广义串并联图,把图缩合成 \(n\le 2k,m\le 3k\) 的图。因为删一度点,缩二度点,叠合重边时,有可能让一个点、一条边承担一个子图的责任,因此需要给点、边分别定义合适的状态。

本题中,为了防止算重,必须定义 \(f_{0/1,0/1,e}\) 表示,对于边 \(e\) 代表的子图,“离子图最近的、子图之外的”两个端点 \(u,v\) 的颜色分别是 \(0/1,0/1\)(有顺序),在此条件下,于 \(e\) 子图内选择独立集,其方案数(思考:若定义 \(f_{0/1,0/1,e}\) 表示,对于边 \(e\) 代表的子图,“最靠近子图外部、但自身处于子图内部的”两个端点 \(u,v\) ......,为什么会算重)。定义 \(g_{0/1,x}\) 表示,对于点 \(x\) 代表的子图,若它的颜色为 \(0/1\),于 \(x\) 子图内选择独立集,其方案数。初始化 \(g_{0,x}=g_{1,x}=1,f_{0,0,e}=f_{0,1,e}=f_{1,0,e}=1\)。删一度点就是 \(g_x\times f\to g_y\),缩二度点就是 \(f\times g_x\times f\to f\),叠合重边就是 \(f\times f\to f\)

注意一点代码细节,例如:不要一边遍历某个 stl 容器,一边删除里面的元素之类的。喜欢写结构体 merge,就要千万注意元素和空元素 merge 的结果,其组合定义可能与常规代数运算不一样。

T-215 26-5-26 B

T-215-1 P11432

建立时间-位置二维轴,用描述法,路径可表示为斜率为 \(\pm 1,0\) 的折线段。用调整法,注意到如果存在

T-215-1-1

就可以削平,答案不劣。因此存在一种最优方案形如

T-215-1-2

对它做 dp,用区间 dp,那就是 \(f_{l,r,0/1,t}\) 表示在 \(t\) 时刻,当前折线最近的两个拐点(一上一下)分别是 \(l,r\),现在位于 \(l\) 还是 \(r\) 处,最小达成时间是多少。最后一维实际无用,故状态 \(O(n^2)\)。改逐步转移,使得单次转移 \(O(1)\)

T-215-2 CF2229G

建立时间-位置二维轴,用描述法,路径可表示为斜率为 \(\pm 1,0\) 的折线段。

T-215-2-1

若图中调整会让答案更优,则黑线不是最优解。因此最优解满足:所有大于 \(x\) 的、斜率为零的位置(“驻留”过的位置),都必须是前缀最大值;所有小于 \(x\) 的“驻留”位置都必须是后缀最大值。将这些位置称为“关键点”。另外,按照时序看驻留的位置,其 \(h_i\) 递增。

更改描述法,运用放生描述法。如果按时序已知所有驻留的位置,那么:如果要走,就一直走到下一个驻留点;必然尽早到达下一个驻留点,也就是说假设路线只有 \(x\to i\),到达第 \(i\) 个驻留点所需的最短时间是 \(t_i\),那无论最优路线实际如何,到达 \(i\) 的时间仍必须是 \(t_i\)。因此只需描述“按时序,所有驻留的位置”。可定义 \(f_i\) 表示:从 \(x\) 开始,尽早走到了(刚刚走到,当前时刻是 \(t_i\))第 \(i\) 个关键点,这段路程中,最大收益是多少。转移需要枚举下一个驻留点,总复杂度 \(O(n^2)\) 的。

其实从 \(i\) 出发,下一个驻留点要么是 \(i\) 后面的第一个,要么是 \(i\) 对侧(位于 \(x\) 异侧)第一个 \(h_j>h_i\) 的关键点。做到总复杂度 \(O(n)\)

T-216 AGC043D 26-5-28 A

又是排列计数题。由于本题是间接构造排列,可能引导人往“钦定字典序、一对一”或“若已知一个排列,该如何判定合法性”的方向思考,但这些方向可能比较陡峭。排列题还有两个方向就是,转零一序列、考虑置换环,但我都没有得到很有价值的结论。排列问题有几个不常见的技巧,例如关注前后缀,元素是否连续;关注从某元素出发的最长上升子序列等,都没有进展。

那么回归本真,回忆排列计数的一般技巧,三种方法,见 T-179。法一,从左往右逐一确定当前位置的值在前缀中排第几大,有一维状态是,当前元素在它和它前面的序列里排第几(相当于将原排列按值域分裂放上下两边);法二,对已知的前 \(i-1\) 个数间“相对关系构成的小排列”,在它的末端(下标为 \(i\) 的位置)添加一个值为 \(i\) 的数字,然后决策这个 \(i\) 应该改为插入到原排列的哪两项之间(原排列分裂放两边);或者是决策这个 \(i\) 应该与原排列的哪一项做交换类似于错排问题。法三,值域轴放外面。每次确定值等于 \(i\) 的位置是谁,可关注连续段,这个连续段可能就是合法段,最终是要求整个排列都合法;或者是实时描述值小于等于 \(i\) 的所有元素构成的子序列形态。

选择法三,值域轴放外面,每次确定值等于 \(i\) 的位置,实时维护全局零一序列。

正序扫描值域轴,不太容易。于是倒序,先考虑全局最大值“能够位于”排列中的哪些位置,显然是后三个位置之一。尝试设 dp 状态,大概就是 \(f_i\) 表示倒序扫描了最大的 \(i\) 个元素的位置,填写这些位置的方案数是多少。考虑全局次大值,可以填在最大值的后面,或者“自己打开”至多三个位置,并占据其中最靠前的位置。因此需要顺便记录“已被前人打开的位置数 \(j\)”。当然,对“打开”也有限制,这就和题面中的三元组有关。实际上,每次“打开 \(i\) 个位置”相当于两步:在排列的末尾,预订连续的 \(i\) 个位置;在某个三元组中,预订连续的 \(i\) 个位置。前者用于计数,后者用于算权(判断合法性就是零一权值)。

带权计数问题。现在可以考虑对一个方案,应该如何算权。把权值必定相同的方案合并算权:转换主体,对于“共预订了 \(x\) 次‘一个位置’、\(y\) 次‘两个位置’、\(z\) 次‘三个位置’”的排列统一算权(显然任一排列只对应一套 \((x,y,z)\))。若能枚举 \(x,y,z\),可以贪心分配,得到权值等于一的充要条件:\(x\ge y\)

现在把权值计算、方案计数综合到扫描值域轴的 dp 中。状态需记录:倒序扫描了 \(i\) 个元素,前人预订过且仍可用 \(j\) 个位置,共预订 \(x\) 次“一个位置”,共预订 \(y\) 次“两个位置”,共预订 \(z\) 次“三个位置”。有 \(x+2y+3z=i+j\)。为了算方案只关心 \(j\),为了算权值只关心 \(x-y\),所以只需记录 \(i,j,x-y\)。转移 \(O(1)\),做到 \(O(n^3)\),无法优化。

若选择法三的变体,值域轴放外面,每次确定值等于 \(n-i+1\) 的位置,实时维护大于等于 \(n-i+1\) 的元素构成的子排列形态。也就是放弃显式“预订”,每次把新元素往里插。

有两种:把新元素 \(n-i+1\) 放到当前子排列开头;把 \(n-i+1\) 插入到某旧元素当初预订的座位当中(延迟决策旧元素的预订数)。若是后者,则对应旧元素已确定的预订数(只考虑大于等于 \(n-i+2\) 的元素,需要该旧元素预订多少座位)不是一就是二。状态需记录:倒序扫描了 \(i\) 个元素,有 \(x\) 个元素已确定预订“一个位置”,\(y\) 个是“两个位置”,\(z\) 个是“三个位置”。有 \(x+2y+3z=i\)。为了算方案只关心 \(x,y\),为了算权值只关心 \(x-y\),所以只需记录 \(i,x,y\)。转移 \(O(1)\),做到 \(O(n^3)\),无法优化。

不采用延迟决策,而是提前决策。当倒序扫描值域轴,元素预订座位时,可以直接在剩余元素中挑选元素,坐到对应位置。或者换句话说,采取魔改版法一。倒序扫描序列轴,逐步确定当前元素在后缀中的排名。

需要记录,排列长度为 \(i\) 的后缀,共有 \(x\) 次“一个位置”预订,共有 \(y\) 次“两个位置”预订,共有 \(z\) 次“三个位置”预订(我说过,一个元素的预订,是在序列轴上连续的几个位置)。有 \(x+2y+3z=i\)。为了算方案只关心 \(i\),为了算权值只关心 \(x-y\)。所以只需记录 \(i,x-y\)。为了方便,逐步转移改断点转移(每次处理一个预订涉及到的,至多三个连续元素,分别确定它们在各自前缀的排名)仍旧 \(O(1)\),做到 \(O(n^2)\)

神奇就在于,如果一上来就用法一,什么也看不出来;如果只用法三,只能被 \(O(n^3)\) 终结;只有先用法三再用法一,才能做出本题。排列计数三大基本方法,要求选手综合应用其中的两种。

T-217 P4382 26-6-3 B

问题严格强于二分图匹配(选手左部点,导师右部点),考虑网络流。因为询问了每个选手的信息,所以只能按照选手编号从小到大,把他们添加到图里。添加一位选手时,实际上应该按照他的志愿,从第一志愿开始分层添加:如果加完某一层后,发现流量变大了一,那么跳到下一位选手。这样就能直接求出第一问的答案。

然而,第二问按照常规思路来说,需要二分。存储每一时刻(每加完一位选手)的整张图,然后把能使待询问选手不沮丧的边都加上,看流量能否增大。复杂度是不对的。其实,网络流中,原图加新边,问流量能否增大一,有个不用重跑的预处理方法。那就是在原图上多做一次(或两次) bfs,例如本题中从汇点开始,求出每个原图点能否只靠原残量网络(容量大于流量的边)到达汇点。当加新边时,只要两端点一个可以从源点到达,另一个可到达汇点,那不就形成新的增广路了。本题中,每加入完一名选手,就做一遍 bfs,然后把每个节点的可达性存下来。这就可以了。

T-218 P9319 26-6-3 A

自适应交互库(包含交互库博弈)较为简易的题目,可以尝试描述交互库的所有可能决策,从而丢弃交互库的“实时决策”性质,将其简单视为“多组询问”。或者说,假设交互库的每一步决策,都只是在所有合法决策中均匀随机。既然如此,本题中可以回忆期望题中的随机删点转排列。假设交互库的决策是:随机一个大小为一号点度数的排列,并维护指针 \(i\)。每次轮到交互库决策时,看 \(p_i\) 能不能走,如果可以就走,反之令 \(i\) 增加一。只需要保证对任一排列,你的策略都能找出结果(博弈题中,取胜)就可以了。

所以什么叫丢弃“实时决策”性质呢,就是假设我有一个打好的表,无论对方怎么做,我都这样输出,也不用管操作合法性,不合法判我负就行了。当然,“打好的表”应该具备一些最基本的性质,例如不自相矛盾,不干“前一步妨碍后一步合法性”的事(只可能因受对方干扰而不合法;存在一种对方的策略,使我方取胜)。丢弃“实时决策”,就可以把交互库、你(或者博弈题中的 Alice 和 Bob)分开观察,转入我们熟悉的描述法领域。

现在丢弃你的“实时决策”性质,从而描述你的策略。不能做“前一步妨碍后一步合法性”的事,因此这策略形如一些“边不相交”路径,路径的端点是两个不同的、与一号点相邻的点。换句话说,仅为满足“存在一种对方的策略,使我方取胜”,就已经要求将一号点相邻的点们两两配对,配对点之间连路径,各路径“边不相交”。这问题容易解决,把一号点按度数拆点(想象:在每条与一号点相连的边 \((1,x_i)\) 的中点上,新建一个点 \(w_i\),删除边 \((1,x_i)\) 改为连 \((w_i,x_i)\)),那么各个连通块独立(此时跑网络流复杂度过高),每个连通块任取生成树,自底向上做树上贪心配对即可达到理论上界(回忆 T-190,构造的第一步是判断无解性,一般和某个数量有关,比如“某个数量的奇偶性合适”或“某个数量处于一个上下界范围内”则问题有解;本题中理论上界:连通块内拆后点个数除以二下取整;有趣的事实,拆后点都是叶子)。

惊喜地发现,只要有任一个配对,无论交互库策略如何,都能取胜。必要条件(存在一种对方的策略,使我方取胜。甚至可以看成,我方代替对方决策/两人共谋)就是充要条件。做完了。也就是说,本题的解法几乎是个纯策略(我方行为不甚依赖对手的行为)。我们等待着一个非纯策略问题,看它能否通过丢弃“实时决策”的办法,得以解决(或启发正解)。

关于配对,是一个套路,见 T-184:无向图上,关键点之间选取尽量多条“边不相交”路径的问题,一般就是把关键点按照度数拆点,转化为配对问题(一条路径相当于配对两个拆后点)。

T-219 P8175 26-6-3 A+

改换题意,改为 Tom 拿的糖果数尽量多,问题核心不变。尝试放生描述法,对一个解,与答案有关的部分只是“拿了多少糖果”,但仅这一项信息太少,达不到放生的要求。改为描述“第 \(i\) 个商店拿 \(b_i\) 糖果”序列 \(b\),再去放生。由题意,若已知序列 \(b\),Tom 一定从左到右,依次把对应商店该拿的糖果拿完。

被放生出来的问题如下:数轴上有一些商店和一些空位,第 \(i\) 个商店必须拿 \(b_i\) 个糖果。拿到糖果后必须访问空位把糖果放下,再拿新的;必须把商店编号小的糖果拿完,才能拿下一个商店的糖果。问最短行动距离。描述拿完第 \(i\) 个糖果之后访问的空位坐标 \(p_i\)(根据商店位置还有 \(b\) 序列可知第 \(i\) 个糖果所在商店的坐标 \(q_i\))。那么答案就是 \(\sum |p_i-q_i|+|p_i-q_{i+1}|\)。用调整法,若 \(p_i>q_{i+1}\),则 \(p_i\) 尽量小才好;若 \(p_i\in[q_i,q_{i+1}]\),则 \(p_i\) 尽量小不劣;若 \(p_i<q_i\),则 \(p_i\) 尽量大才好。换句话说,\(p_i\) 要么是大于 \(q_i\) 的最近空位,要么是小于它的最近空位。更进一步地,若 \(q_i=q_{i+1}\)\(p_i\) 只会是距离 \(p_i\) 最近的空位。假设里第 \(i\) 个商店最近空位的距离是 \(d_i\)

考虑到 Tom 最终停留在“最后一个 \(b_i\neq 0\)”的商店,不妨把从原点到该位置的距离提前算上。剩余需要移动的距离,会是怎样的呢?根据上述调整分析,假设第 \(i\) 个商店后面第一个空位坐标为 \(r_i\),第一个 \(b_j\neq 0\) 的商店坐标为 \(s_i\)。那么剩余距离就是 \(\sum 2d_i(b_i-1)+\sum \min(2d_i,\max(0,2r_i-2s_i))\)(求和只针对 \(b_i\neq 0\) 的商店)。

回到原题,原题是在只考虑前 \(x\) 个位置构成的前缀,\(x-1\ge \sum 2d_i(b_i-1)+\sum \min(2d_i,\max(0,2r_i-2s_i))\) 均成立的前提下,求 \(\sum b_i\) 最大值。改描述法,这相当于在第 \(i\) 个商店可以选择若干红糖果,代价为 \(2d_i\);可以选择至多一个黑糖果,代价为 \(\max(0,2r_i-2s_i)\),只要求红黑糖果数目之和 \(\le a_i\)(条件一),而且前 \(x\) 个位置构成的前缀内商店代价和 \(\le x-1\)(条件二),最大化全局红黑糖果数目和。用不劣调整法(全局红黑糖果数目和不变,维持条件一,调整以进一步满足条件二),对某合法解,可选择其中一个黑糖果(尝试一下,大概就是选个红糖果向右移一格,把红变黑之类,看看它的组合意义。这里只列出最有意义的那一种调整),向右移动到位置上的下一个商店(要求两个商店位于同一商店连续段),只要能移,全局红黑糖果数目和不变;条件一维持;条件二更易满足。换句话说,最优解中黑糖果不能向右移动到连续段内下一个商店。也就是说,每个黑糖果要么位于连续段内最靠右 \(b_i\neq 0\) 商店的紧邻左侧,要么位于另一个黑糖果的紧邻左侧,要么位于连续段末尾。

刚才的问题不好算,重点在于黑糖果价值与 \(s_i\) 有关,而 \(s_i\)\(b\) 序列本身有关。然而现在 (*),每个黑糖果对应的 \(s_i\) 恰好等于对应位置连续段内紧邻右侧的商店坐标。因此红黑糖果实际价值固定只和 \(i\) 有关。

用最优化的两种处理办法,要么 dp,要么贪心。看限制与 \(x\) 有关,那总归是要扫描 \(x\) 轴的。扫描 \(x\) 轴,每次反悔贪心显式调整,动态维护当前最优解,即可。

T-220 P11810 26-6-3 A

平面图,障碍物,连通性,回忆 T-113。注意 T-113-3 十分特殊,仍需原有的不严谨思路才能处理;其它常规题目,可做补充如下:对平面图建立对偶图,若一个障碍物导致原平面图的一些边失效(你要注意,某些特殊情况下,失效的边不只是与障碍物直接相连的边,而是一切“只要此处存在障碍物,则这条边不可能被合法路径经过”的边),则视为这个障碍物导致对偶图上“垂直于这些边”的边被激活。特别地,若原图是有向图,则“垂直于边 \(e\)”的对偶边,应该按照“若你面朝 \(e\) 的终止端点,你的右手向左手方向”定向。若要求原图 \(s\to t\) 的最短路。应该在原平面图的外部面边界上,选择两个点,并跨过外部面给这两个点连一条边,把外部面一分为二,两个新面记作 \(S,T\),使得 \(s\) 在新面 \(S\) 的边界上,\(T\) 在新面 \(T\) 的边界上。建立对偶图后,对偶图 \(S\to T\) 的最大流等于原图最短路。

本题中,在对偶图上每增加一个障碍物就激活四条边,如果对偶图存在环,那么(原平面图上)环内环外不互通,这时就需要判断环内是否存在城镇。注意该环在平面图上形如一个连通块。如下图,棕色部分是障碍物,红色部分是被激活的对偶图边,绿色部分是原平面图的环内元素。

T-220

见 T-182,极其复杂的数据结构存在性问题,不妨异或哈希,从而只需关注、维护一个数值。也就是给每个城镇赋随机哈希值,在每个障碍物八连通块上维护,该连通块内,每个障碍物“本障碍物右边界以右,同一行内,所有城镇哈希值异或和”的异或和。若成环,则该异或和实质上就是“环内城镇哈希值异或和”。左右移动只需单边修改,然而上下移动就不行。将上下移动带来的增量放到横边上,改为在每个障碍物八连通块上维护,其所有障碍物“上边界、右边界边权异或值”的异或和(上边界边权只处理上下移动带来的增量)。这样,每次移动只会更改一条边的权值。

T-221 UOJ1037 26-6-3 S*

第二道 S*。这道题把几乎所有常见的数据结构技巧熔为一炉。

\(C=1,D=n-1\)。首先二分是容易想到的,只需在线问 \([L,R]\) 内是否存在 \(l<r,b_r-kr\ge a_l-kl\)。对区间查询问题,一般考虑莫队,分块,扫描线,猫树。本题中,应选择猫树。若 \([L,R]\) 挂在猫树节点 \(m\) 上。猫树的核心就是分治。也就是说,分两部分,先问 \(l\in[L,m],r\in[m+1,R]\) 内是否存在;再问 \(l,r\in[L,m]\) 还有 \(l,r\in[m+1,R]\) 内是否存在。猫树分治允许考虑“与当前猫树节点有关的‘贡献区间’”,在本题中,就是指“被节点区间包含”。换句话说,不仅考虑第一部分“跨过当前猫树节点中点的‘贡献区间’”,还要用到第二部分“被当前节点某儿子节点包含的‘贡献区间’”,使得一个询问只访问一个节点就得到解决。

数据结构题目分三部分,预处理,查询,修改。本题中没有修改,查询能做的事情有限,故灵活性主要集中在预处理部分。第一部分是对固定 \(m\) 动态查询,给定 \(L,k\)\(r\in[L,m],\max b_r-kr\)。从 \(m\)\(l_m\) 扫描并维护可持久化李超线段树即可。至于第二部分,最好是预处理 \(l,r\in[L,m]\) 的答案,可以在最初做一遍分治。因此总复杂度 \(O(n\log^2 n+q\log^2 n)\)。由于每次查询相当于做二分、做查询,不妨结合起来做可持久化树上的二分(每次二分要同时在 \([L,m],[m+1,R]\) 的两棵李超树上做),就能做到 \(O(n\log^2 n+q\log n)\)

预处理部分看起来不太能优化,开始关心单调性。注意到斜率具备单调性,因此所谓李超树是不必要的(借鉴斜率优化、决策单调性优化 dp),只需决策单调性二分栈(无需二分,因为直线交点可以 \(O(1)\) 求),换句话说,维护可持久化凸包,而不是可持久化李超树(回忆:复杂数据结构的可持久化,例如可持久化并查集,一般建立在可持久化数组的基础上)。还是可持久化线段树来实现,除了卡常外并没什么用(复杂度完全一样)。

回忆 (*),多版本问题,除了可持久化,就是建立版本树。对于凸包,每次加入一条直线即入栈,弹出一条直线即出栈。出栈即版本树上回溯。只在每个结点维护对应加入的直线,这样每个结点只是一条直线,每个版本的凸包,就是根到某点的路径上,所有直线依顺序加入的结果。这样就把“第一部分”的预处理时间复杂度、空间复杂度降低至 \(O(n\log n)\)

那查询怎么办呢?单次查询复杂度又退化回 \(O(\log^2 n)\)。考虑李超树部分给人的启发,该如何同时在两个凸包上二分(假设凸包已知分别为 \(C_1, C_2\),如何找出最大的 \(k\) 满足 \(C_1(k)-C_2(k)\ge 0\),其中 \(C_1\) 下凸,\(C_2\) 上凸)。如果以某凸包为中心做二分,就需要处理“\(C_1\) 上第 \(i\) 个节点的横坐标,对应 \(C_2\) 上的第几个节点,称为 \(q_i\)”,这是不可能的。因此二分不能以任何凸包为中心,考虑类 kdt 的方式 (*):已知 \(k\) 位于 \(C_1\) 上第 \(l_1,r_1\) 个节点横坐标之间;同时也位于 \(C_2\) 上第 \(l_2,r_2\) 个节点横坐标之间。希望在询问 \(C_1(m_1)\) 或者 \(C_2(m_2)\) 之后,缩减 \([l_1,r_1],[l_2,r_2]\) 中的至少一个,到原来大小的一半。例如询问 \(C_1(m_1)\),你会发现 \(C_1(m_1)-C_2(r_1)<0<C_1(m_1)-C_2(l_1)\) 时,\(C_1(m_1)-C_2(q_{m_1})\) 和零的大小无从比较,这就完蛋了。所以你要同时 (*) 询问 \(C_1(m_1),C_2(m_2)\),你发现:不妨 \(X_1(m_1)<X_2(m_2)\) 时,\(C_1(m_1)-C_2(m_2)<0\),则 \(C_1(m_1)-C_2(q_{m_1})>0\),因此 \([l_2,r_2]\to [l_2,m_2]\)。对称情形亦然。如果某一时刻发现 \(l_1=r_1\),那就是个边界情况,暴力算出 \(q_{l_1}\) 之后还拥有 \(O(\log)\) 的时限呢,随便做一下。因此对已知的两个凸包,可以 \(O(\log n)\) 处理一次“两个凸包上的二分”。

实际上的查询情形并不是“已知两个凸包”。而是在两棵版本树的根到点路径中,对应的凸包上二分。这是个树上数据结构问题,看来没什么差分的余地,也没什么链-子树对称的可能,也不能拍到 dfs 序上,那只能树剖了。为了保持树剖时空复杂度正确,每条重链只需维护“依次从链顶到链尾,每个节点挂的直线”构成的子凸包(易知确是凸包),其实就是把两个凸包各自的存储数组拆成了 \(O(\log n)\) 个连续段而已。这样的话,直接上手询问 \(C_1(x)\) 是做不到 \(O(1)\) 的。大概就是说,把每个连续段的开头位置的 \(X,C\) 求出来 (*),按照 \(X\) 归并后,双指针一手,即可定位出答案位于两个凸包的哪一段连续数组中,然后在这一段二分。

至于上述“第二部分,最好是预处理 \(l,r\in[L,m]\) 的答案,可以在最初做一遍分治”。具体阐释:假设这个答案放在 \(a_{L,m}\)。以之为主体,则这种主体只有 \(O(n\log n)\) 个。考虑递推关系,\(a_{L,m}=(a_{L,m'}+a_{m',m})\),当然这里的加法,除了取最大值,还需要考虑 \(l\in[L,m'],r\in[m',m]\) 的最大答案,似乎需要做那个凸包上二分,复杂度太劣。将答案记在 \(b_{L,m'}\),以之为主体,注意对同一个 \(m'\) 和不同的 \(L\),这一部分答案可以双指针。于是做到“第二部分”预处理 \(O(n\log n)\)

所以数据结构题目,一定要将待求解的多个本质相同子问题像刚才一样,当成数组或函数抽出来。然后关心:改换贡献主体,递推,改换贡献顺序,合并连续段统一计算。

另外就是像本题这样的,贡献主体 \((l,r)\) 是个点对的问题,大概率需要画在二维图上考虑,类似 NOIP2025 T4。具体地,一般用分治或者分块处理。若通过分块处理,每次查询就只需考虑 \(l,r\) 均属于整块;\(l\) 属于散块,\(r\) 属于整块;\(l,r\) 均属于散块。类似《时代的眼泪》。

\(D=n-1\),回忆 NOIP2025 T4 的做法,以定长 \(C\) 分块。每次查询时,为了 \(O(\log n)\) 单次算出 \(l,r\) 属于互异散块的问题(显然 \(l,r\) 不能属于同一散块),需要预处理什么?只需每个块的前后缀凸包版本树,凸包上同时二分即可(假设 \(l,r\) 所在块间隔至少一个块,也就是说 \(l,r\) 所在块相邻的情形我们先不计算,这部分贡献在后面讨论)。为了算 \(l\) 属于散块而 \(r\) 属于整块的情形(假设 \(l,r\) 所在块间隔至少一个块),需要每个块开头位置,向后到整个序列末尾的凸包版本树,仍旧在凸包上同时二分。为了算 \(l,r\) 均属于整块的情形(假设 \(l,r\) 所在块间隔至少一个块),开一棵叶子节点表示“一个整块”的猫树,应该能搞定,见下图(这部分做法不保真)。

T-221-1

“第一部分”,\(m\) 就是分治中心。建立绿色部分凸包、黄橙色部分凸包,同时二分;剩余的跨过分治中心的贡献,就是 \(m\) 到橙色部分的贡献,也可同时二分;还有 \(m\) 到黄色部分的贡献,但此时先不计算,因为是 \(l,r\) 所在块相邻的情形。“第二部分”,递推合并信息只需考虑 \(l\) 属于绿色、\(r\) 属于黄紫色部分的,再额外与红色、紫色部分的答案取 max 就可以了。参照原来的猫树做法。

现在,对一次查询,已经处理到只剩:\(l\) 属于散块 \(r\) 属于与之相邻的整块;\(l,r\) 分别属于相邻的整块。特殊情况下,还有 \(l,r\) 属于相邻的散块。考虑特殊情况应该怎么做。这种题目有一个套路叫做重叠(overlap),见下图。

T-221-2

对于相邻块(绿色块,黄色块),如果 \(l\) 在红色位置,则 \(r\) 必须超过灰色位置。如果把两个块叠合,则相当于 \(r\ge l\)。如果限制不是 \(r-l+1\ge C\) 而是反过来,那么叠合时需要将其中一个块倒序放置,但这与本题无关。总之,叠合之后,就变回标准叙述过的分治问题了,\(l,r\) 分别属于相邻的整块 的情形已经可以简单预处理。但是,若 \(l,r\) 属于相邻散块,还需要一个 \(O(\log n)\) 的做法(\(l\) 属于散块 \(r\) 属于与之相邻的整块,被上述问题包含了)。见下图。

T-221-3

如图,叠合后,是 \(l\) 属于蓝色部分,\(r\) 属于红色部分。这无法通过合并预处理凸包实现。因为时限 \(O(\log n)\),采取类线段树查询的递归结构是可行的(不要忘了,魔改版线段树可以解决很多单答案问题)。如果线段树 mid 位于 \(l,r\) 之间,就把当前问题切分成两个形如 \(l\in[n_l,L],r\in[n_l,n_r]\) 的“小问题”(其中 \(n_l,n_r\) 是某个线段树节点的统治范围),“小问题”还可以向更深层自递归成“小问题”,合并时需要询问 \(l\in[n_l,L],r\in[n'_l,n'_r]\) “小小问题”的答案,其中 \(n,n'\) 是父节点相同的。建树时参照“标准分治”“第二部分”做预处理,“小问题”合并时的复杂度就变成 \(O(1)\)。如果线段树 mid 位于 \(l,r\) 的同侧,则当前问题切分成“当前问题”和“小小问题”,也可以 \(O(1)\) 合并。

这就把 \(D=n-1\) 做完了。对于 \(D\neq n-1\) 的情形,把二维图画出来,如下。

T-221-4

需要的就是黄色与绿色部分,根据 NOIP2025 T4 的讨论,尝试把连续段合并统一处理。本题中平行四边形也是容易 \(O(\log n)\) 算出的。剩余的黄色等腰三角形,在 NOIP2025 T4 中是拆成内接正方形与两个小等腰三角形解决的,但本题中无需如此,因为黄色等腰三角形与 \(D\) 无关,相当于一个 \(D=n-1\) 的询问。于是总复杂度 \(O(n\log n+q\log n)\)

子问题间的递归;已解的部分分,思想向外拓展,从而解决整道题目;像 NOIP2025 T4 那样,关注信息的可加性、可重算性,从而把待求图形切分成若干易于处理的小块(每个小块就是容易统一计算的连续段),再合并信息。

T-223 P10802 26-6-5 B

这一类 dp 构造题,转移一般都极为容易,但如何找出状态?通法:先设计一个不足够的“状态一”,再根据该尝试转移一次。为了描述“状态一”转移一次后得到的状态,我们需要引入“状态二”。如果“状态二”对转移封闭,那么设计完毕。

对于本题,不足够的“状态一”就是 \(f_i\) 表示在 \(i\) 个元素中可能有人患病,最优决策下期望步数是多少。转移一次,就是选前 \(j\) 个人询问一下,如果 \(j\) 个人都没患病,就向 \(f_{i-j}\) 转移,反之得到“状态二”需要两维描述:\(f_{i,j}\) 表示在 \(i\) 个元素中可能有人患病,问了一下发现前 \(j\) 个人中至少有一个人患病,最优决策下期望步数是多少。“状态二”对转移封闭。于是做完了。

T-224 QOJ18337 26-6-11 B+

描述法只对答案服务,只需以各个专家关注的矩形为主体,看它两端点的黑白情况,用 BW,WB(零一状态)表示,即可计算答案。至于合法性判定,对黑元素,必然满足所在行、所在列都足够长。取边界元素,找出每一行、每一列中,最远的黑元素,则这些行列的直方图至少那么长;在“恰好那么长”的基础上,如果没有把任一“想要白元素”染成“实际黑元素”,则合法。换句话说,设在第 \(i\) 行中,列标号最大的黑元素的列标号为 \(a_i\),列中对称定义为 \(b_j\)。若要合法,则对任一白格子 \((i,j)\)\(b_j>i,a_i>j\) 中需要存在一个不成立。

取反面,极大转存在。若存在白格子 \((i,j)\),使得存在黑格子 \((i',j),(i,j')\) 满足 \(i'>i,j'>j\),则不合法。现在 dp,不妨扫描 \(x\) 轴,每次一并处理左端点为 \(t\) 的所有矩形。发现“这一列”矩形按照 \(y\) 从大到小形如 WB,WB,WB,...,WB,BW,BW,...,BW。称右侧没有矩形的矩形为“好矩形”,则:第一种情况,“这一列”内最下侧的“好矩形”仍是 WB;第二种,这一列全都是 BW。因此一列矩形的状态可以用一个整数 \(s\) 唯一表示。故定义状态 \(f_{x,s}\)

列之间的矩形互相影响,只会出现在“某列矩形右端点横坐标,等于某列矩形左端点横坐标”的情况下,这时才需要列间转移(否则列间独立)。因此将矩形按照左端点模 \(k-1\) 分组,组间没有关系;组内容易转移,复杂度 \(O(n)\)。当然,实际上需要排序,故总复杂度 \(O(n\log n)\)

T-225 P9987 26-6-12 A

看到贡献式满足可加性、可减性(因此无论是给贡献,还是受贡献,都可以分割、差分),不妨差分变成 \(i\le j,a_i\le a_j\) 还有 \(i\le l-1,a_i\le a_j\) 两部分贡献。前者无需考虑,关键是后者。尝试根号做法,分块。分块本质上就是将“一维相邻或相同的连续段”暴力合并为一个主体(不同于:有优良性质时,将多维相邻或相同的连续段,自然地合并为一个主体),接受或发送贡献。取位置轴分块,从预处理、修改、查询的角度,修改似乎是重头戏,换句话说以 \([1,l-1]\) 元素为主体,向后续元素贡献。

那么 \([1,l-1]\) 中的一些整块,对后面如何贡献?考虑到可加性,整块之间没有关系。对每个整块,只需预处理扫一遍值域轴(算出 \(a_k=t\) 的元素受多少贡献),再用树状数组实时维护序列轴(计算各个序列位置分别受到多少倍“本块贡献”)。\([1,l-1]\) 中的散块(称之为 \(S\)),转换主体,以 \([l,r]\) 元素为主体接受前面的散块贡献,仍取位置轴分块。\([l,r]\) 中整块受贡献,整块之间没有关系。具体来说,对每个块,有效值域只有 \(O(\sqrt n)\) 种,可预处理;查询时则允许 \(O(\sqrt n)\)。遇到修改操作时,枚举 \(S\) 内所有元素,分别给 \([l,r]\) 涉及到的整块做修改(差分,只在最前最后那两个块的,树状数组维护的值域轴上做修改。思路来源是枚举 \(S\) 元素后,时间复杂度余额只支持单次修改)。单点查询时,扫描一个后缀的 \(O(\sqrt n)\) 个块,在值域轴上各查询一次。至于 \(S\)\([l,r]\) 中散块的贡献,每次归并排序计算。

总复杂度 \(O(n\sqrt n\log n)\)

当然,最初时也可不差分而是直接分块,拆成散块内部,左散对右散,左散对整块,整块内部,整块对右散五部分贡献,类似《时代的眼泪》。总之 \((i,j)\) 数对的问题,可在序列轴上分别对 \(i,j\) 分块。

T-226 P8990 26-6-17 B+

回忆 T-187,我曾强调,点减边容斥常用于统计树上连通块的数目。树上的主体,常见的就只有点,边,子树,连通块,树链这五种。

先选主体。本题,若关心全体白点,就应以子树为主体,难以处理,首先“美丽的”这一条件就难以刻画。对称地关注全体黑点,“美丽”时黑点构成连通块。可以点减边容斥计算黑点连通块数目、白点连通块数目。

再选轴。树轴是动态的不好维护,先放一边。修改轴几乎只能放外面扫描。内层应是维护时间轴(依次点灯的时间轴),定义 \(f_i,g_i\) 分别代表黑白点在第 \(i\) 时刻的连通块数目,则答案就是 \(\sum [f_i=1]g_i\)。存在转最值,\(f_i\) 下界是一,因此只是 \(f,g\) 在线区间加减,求所有 \(f_i\) 取最小值时的 \(g_i\) 之和,这也容易。

T-227 三联画 26-6-17 A

T-227-1 P16433

回忆排列计数的一般技巧,见 T-216。有两种理解方式。

第一种理解方式,已知某个长度为 \(i\) 且具备某些性质(用其它 dp 状态 \(j,k,...\) 描述)的排列,对它做微调,得到长度为 \(i+1\) 的排列。用这种思想解释 T-216 所说的前两种方法。法一,当前元素在它和它前面的序列里排第几,就相当于把原排列按值域分裂放上下两边。法二类似于错排问题,对已知的前 \(i-1\) 个数间“相对关系构成的子排列”,在末端添加值为 \(i\) 的数字,然后决策此数字应该改为插入到原排列的哪两项之间,就相当于把原排列分裂放两边;或者是决策这个 \(i\) 应该与原排列的哪一项做交换。

第二种理解方式,扫描一个轴的同时,用 dp 状态维护另一个轴。用这种思想解释 T-216 所说的全部三种方法。法一和法二都相当于扫描位置轴,维护“位置轴上前 \(i\) 个元素,放在值域轴上构成子序列的形态”。法三相当于扫描值域轴,维护“值域轴上前 \(i\) 个元素,放在位置轴上构成子序列的形态”。

综合上述两种理解方式,排列计数的一般技巧,本质上有六种方法:
法一,扫描位置轴,微调策略是值域分裂。
法二,扫描位置轴,微调策略是位置分裂。
法三,扫描位置轴,微调策略是位置交换。
法四,扫描值域轴,微调策略是位置分裂。
法五,扫描值域轴,微调策略是值域分裂。
法六,扫描值域轴,微调策略是值域交换。
当然,考虑到位置-值域对称(也可理解为正排列-逆排列对称),实际上只有三种方法,只看最外轴如何选取。因此,排列计数的一般技巧也可以迁移到“轴非链”的地方,例如树拓扑序计数中去(视拓扑序为待计数排列,可以选择树轴为最外轴,值域轴为内层轴)。

近期我计划推出 The Art of the Induction III。我初步构想的 dp 部分,最重要就是定义状态,但定义状态时必须考虑转移。状态定义时需要考虑五个要点。第一个是,轴(被扫描的最外层轴,被维护的内层轴)。第二个是,描述法(描述法只跟答案计算过程还有选取的主体有关)。第三个是,逐步转移(一般而言都是逐步)还是断点转移。第四个是,信息推后确定(尽量只在信息影响状态转移时才确定它,一般都是如此)、信息提前确定(该信息对未来转移至关重要,但若现在不确定并记录它,未来就没机会了。例如耳分解状压最优化题)与信息释放(某些信息不涉足未来转移,可以与 dp 解耦,无需记录而是直接贡献给答案,或贡献给 dp 数组。注意有许多信息可以在 dp 开始前就解耦)。第五个是,先粗糙再扩充(无法记录信息或完成转移时扩充,如 T-223)。

对于本题,A 性质只需选用法一,定义 \(f_{i,j}\)。至于整道题怎么做,选逐步还是断点,这是个问题。若断点,则相邻 \(p_i\neq 0\) 应视为一个元素来处理,似乎很复杂,而且段之间关系还挺密切,故选择逐步。也就是说,首先定调:最外轴扫描位置轴,内层轴维护值域轴;描述法不直接,应根据扫描过程逐步描述;主要是断点转移;主要是信息推后确定。

核心难点是描述法不直接。但关于这个未知的 dp 状态,“定过的调”都是金科玉律。若把信息推后确定做到极致,是什么样呢。在逐步转移过程中,若按位置轴扫描到“首个 \(p=0\) 连续段内的元素”\(i\),此时转移涉及的信息不超出 A 性质做法的范畴,套用 \(f_{i,j}\) 为“粗糙的状态定义”就够用。当遇到第一个 \(p_i\neq 0\) 的元素,为了转移,所需的信息至少得有,前 \(i-1\) 个元素中有几个小于 \(p_i\)(对绝对大小的限制。对任一元素,绝对大小都未确定),所确定的值 \(k\) 放到状态里。因此当前状态变为 \(f_{i,j,k}\) 表示考虑前 \(i\) 个元素,当前元素在其中排位第 \(j\),有 \(k\) 个元素绝对大小小于当前最后一个 \(p_j\neq 0\)\(p_j\)(记作 \(q_i\))。

这能转移吗,当然可以,前缀和优化做到 \(O(n^3)\)

T-227-2 P11426

扫描值域轴,维护“环子序列”状态。从答案计算的角度,描述法必须处理每一个缝隙。因此需记录 \(R<B,R>B,B<R,B>R,BB,RR\)(顺时针)分别有 \(a,b,c,d,e,f\) 个。实则只记 \(i,a,b,c\) 就能计算 \(d,e,f\):由 \(i\) 得“前 \(R\) 个数”等于“后 \(R\) 个数”为 \(i_1\),“前后 \(B\)”为 \(i_2\) 个,那么 \(a+b+f=i_1,c+d+e=i_2,c+d+f=i_1,a+b+e=i_2\)。这方程组实际只足够定死 \(a+b=c+d=i_2-e=i_1-f\),记录 \(a,b,c\) 就能推出 \(d,e,f\)。做到了 \(O(n^4)\)。答案用 \(a-b-d=c-2b\) 表示。

计数问题可以考虑 dp,组合数学或容斥。本问题只涉及相邻元素大小关系,我们知道欧拉数问题可用容斥解决。考虑本来要什么:为了算答案,需要求出所有形如 \(f(c,b)\) 表示最终恰好 \(c,b\) 的排列有多少个。定义 \(g(C,B)\) 表示钦定 \(c\ge C,b\ge B\) 的排列个数。容易得到贡献系数,本质上是二项式反演,反演的过程可以 NTT 优化。因此只需关注 \(g(c,b)\) 的求法。

\(g(c,b)\) 解耦。第一部分“\(c,b\) 边的绝对形态”。第二部分“所有元素的排列方式”可以直接乘 \((n-c-b-1)!\) 的系数。第一部分,选取值域轴 dp,定义 \(f_{i,p,q,r,s}\) 表示考察前 \(i\) 小的元素,已经定好的 \(c,b\) 边分别有 \(p,q\) 个,定了一半的有 \(r,s\) 个。注意到 \(c,b\) 边互不干扰,因而可以解耦,\(f_{i,p,r}\) 做到 \(O(n^3)\)

定义 \(r,s\) 的缘由,是逐步转移导致“最后一个操作没有结束”导致信息提前确定。想要改为断点转移,参照 T-216 的最终解法。以计算 \(B<R\) 的 dp 为例。扫描到值较大的 \(R\) 元素时,再配对某个“已访问过的,较小的”\(B\) 元素,信息推后确定,做到 \(O(n^2)\)

T-227-3 CF1750G

若排列 \(p\) 是最大的排列,也就是取消字典序限制,称 \(f(p)=x\) 的排列个数为 \(a(x)\)。计数问题,dp 组合数学或容斥。容斥,钦定至少 \(x\) 个缝隙不满足 \(p_i=p_{i-1}+1\),称这个答案是 \(b(x)\)。则 \(b(x)=\binom{n-1}{x}(x+1)!\)。二项式反演,得 \(a(x)=\sum_{y=x}^{n-1}(-1)^{y-x}\binom{y}{x}b(y)\)

上字典序限制,只需枚举一个前缀 \(i\) 要求 \(p'=p\),再枚举 \(p'_{i+1}<p_i\),往后填数就随意了。枚举完后,把待求的多个本质相同问题抽象成函数,\(a(n_0,x)=\sum_{y=x}^{n_0}(-1)^{y-x}\binom{y}{x}\binom{n_0}{y}(y+1)!\)(对该函数的一切调用中,只存在 \(O(n)\) 个不同的 \(n_0\) 参数,但每个 \(n_0\) 都枚举了所有 \(x\) 来调用),做到 \(O(n^3)\)

推一下式子。\(\binom{y}{x}\binom{n_0}{y}=\binom{n_0-x}{y-x}\binom{n_0}{x}\)。复杂函数要尝试解耦,使之变成参数更少或计算过程更简易的简单函数,只见(换元 \(y'=y-x,n'=n_0-x\)):

\[a(n_0,x)=\binom{n_0}{x}\sum_{y'=0}^{n'}(-1)^{y'}\binom{n'}{y'}(y'+x+1)!=\binom{n_0}{x}q(n',x) \]

对于这种本质相同问题的一般计算方法,有递推、统一计算、改换主体等。尝试一下递推,先考虑与待求式在某些轴上相近(本题中有 \(n',x\) 两个轴)的式子。换句话说,首先关注 \(q(n',x),q(n',x-1),q(n'-1,x)\) 等式子间的差异,常常通过做差来对比。

\[q(n',x)-q(n'-1,x)=O(1)+\sum_{y'=0}^{n'}(-1)^{y'}\left(\binom{n'}{y'}-\binom{n'-1}{y'}\right)(y'+x+1)! \]

\[q(n',x)-q(n'-1,x)=O(1)+\sum_{y'=0}^{n'}(-1)^{y'}\binom{n'-1}{y'-1}(y'+x+1) \]

换元 \(y''=y'-1\),得

\[q(n',x)-q(n'-1,x)=O(1)-\sum_{y''=0}^{n'-1}(-1)^{y''}\binom{n'-1}{y''}(y''+x+2)=O(1)-q(n'-1,x+1) \]

因此 \(q(n',x)=q(n'-1,x)-q(n'-1,x+1)+O(1)\),容易递推做到 \(O(n^2)\)

T-228 QOJ4861 26-6-23 B

给定一个长为 \(n\le 10^5\) 的排列 \(a\) 和加密方式 \(p\)(也是个排列),定义 \((f^k(a))_i=(f^{k-1}(a))_{p_i},(f^0(a))_i=a_i\)。有 \(q\le 10^5\) 次询问,每次交换 \(a\) 中的两个元素,或者交换 \(p\) 中的两个,或者询问 \(f^x(a),f^y(a)\) 的字典序大小关系。

排列题目,考虑置换环 \(i\to p_i\),本题中的置换环可用平衡树维护。那么 \((f^x(a))_i\) 就是 \(i\) 所在位置沿环行走 \(x\) 步到达的位置 \(j\) 对应的 \(a_j\)。字典序比较问题,常常就是求出 lcp 然后比较下一个元素。其中“比较下一个元素”是容易做的,只需会求 lcp。

取反面,最长公共前缀的反面是“最小的满足 \(f^x(a)_i\neq f^y(a)_i\) 的位置 \(i\)”。取各个环为主体,对一个环,若其长度满足 \(x\equiv y(\mod l)\),则一切涉及该环的“单元素比较”都会返回“相等”的结果。若反之,则全都不相等,而涉及到它的第一个比较,就是环上最小的元素编号。

因此将环按照长度分组(换主体为:长度为 \(i\) 的一切环),每次枚举一切长度,就可以了。不同长度的种类数只有 \(O(\sqrt n)\) 种。

T-229 CF1060F 26-6-24 B+

对每个点分别求。无根树先定根,就定成当前求的那个点。期望题,首先转成给每条边赋删除顺序,排列计数,则使权值乘二分之一系数的边就是,到根链上的“前缀”最大值边。

上描述法,答案计算分两部分,一个是方案,一个是权值。先用 01 描述哪些边是“前缀最大值边”,这样就能算权值。

做逐步描述,在已知上述 01 序列的基础上考察方案计算。必然是从下向上扫描树轴做子树合并,仿照树上拓扑序计数的经典 dp,\(f_x\) 表示子树内元素的相对大小关系种数,则子树间合并无碍。至于定子树根的大小,因为这个根不能把子树内“前缀最大值边”搞死,到最终也不能把任意“不是前缀最大值边”搞活。因此需要记录子树内所有“前缀最大值边”中的最低排名 \(i\),还有所有“还活着的不是最大值边”的最高排名 \(j\)

回到原问题,只需定义 \(f_{x,i,j}\) 做“类 dp 套 dp”的联合计算就可以了,应该是能做到 \(O(n^5)\)

无法优化,回顾我们采取了什么处理方式:轴与描述法的选取较为简易,主要是逐步转移信息推后确定。改断点转移似乎有一定难度。改信息提前确定或信息释放,需要抓住这一点:信息推后确定时,大概是,现在记录下来一些“接口”“选项”“限制”供未来元素选择或遵从。提前确定或释放的策略则是,在“接口”“选项”“限制”建立的同时,确定某个未来元素(可能是抽象元素,例如,\(a,b,c\) 三个具体元素中的最大者)某个方面的值。要求是:对于任意情形,只要这个方面等于你所确定的值,就必能把接口接上,或满足当前限制。这样一来,只需记录“你所确定的值”(能做信息释放时甚至无需记录),而无需记录“接口”“选项”“限制”本身。

于是,更改状态为 \(f_{x,i}\) 表示,假如确定了从 \(x\) 到根的链上最大边权在子树内排名为 \(i\) 时,子树内所有可能的“01 序列-边相对大小关系”权值之和。做到 \(O(n^4)\)

T-230 CF1097G 26-6-24 B

显然拆组合意义,定义 \(f_{x,i}\) 表示考虑所有虚树的 \(x\) 子树部分,选出 \(i\) 条边(可重复,有顺序,但重复边之间无顺序)的联合方案数。除了子树合并,实际转移还要考虑到 \(x\) 选不选,需要加零一状态,比较麻烦,但不是重点难点。做到 \(O(nk^2)\)

\(n^k\) 除了直接像刚才那样拆,还有类似 T-103-4 的 trick 就是 \(n^k=\sum S(k,i)i!\binom{n}{i}\),表示钦定某 \(i\) 个元素成为那 \(k\) 次选取的元素的并集。因此转而定义 \(f_{x,i}\) 表示考虑所有虚树的 \(x\) 子树部分,选出 \(i\) 条边(不可重复,无顺序)的联合方案数。因为 \(i\le \mathrm{siz}_x\) 所以能做到 \(O(nk)\)

T-232 CF771E 26-7-6 B+

\(2\times n\) 的矩阵,最外轴大概率取 \(n\) 一维。值域数据范围过大,逐步描述难以接受,因此大概率断点转移。断点作为关键位置,应是某个矩形的左边界或右边界。同一列至多存在两个矩形。故可得暴力 dp,大致是 \(f_{i,j}\) 表示扫描到 \(\max(i,j)\) 时,最后一个“上矩形”右边界为 \(i\),最后一个“下矩形”下边界 \(j\)(若只有一个矩形用 \(f_{i,i}\) 代称),最多选取多少矩形。单个状态的“受贡献”式有效转移 \(O(1)\),例如最后一个转移的是“上矩形”时,只会选择最近的合法左边界 \(l\),否则假设选择左边界 \(l'\)\([l',l],[l,i]\) 分两个矩形,调整不劣。

关键是状态爆炸。在此处考虑最短路优化行不通,因为两维“上下矩形”无法解耦。然而,若只关心“宽为二的矩形”作为关键矩形,则解中相邻两次关键矩形之间的部分可以解耦。换句话说,定义 \(f_i\) 表示扫描到 \(i\) 时,最后一个“宽二矩形”右边界为 \(i\),最多选择多少矩形。

断点转移使用“受贡献”法,扫描 \(i\) 的过程中数据结构维护“从 \(j\) 转移开来的转移边权值 \(g_j\)”,显然 \(g_j=f_j+...\),“...”表示从 \(j\) 开始解耦地考虑上下两行一直到 \(i\),最多选择多少矩形。对于解耦的两部分,此过程都应是扫描右端点的贪心,能操作就操作。换句话说,数据结构维护 \(h_{0,j}\) 表示从 \(j\to i\) 的过程中贪心选取的最后一个“上矩形”右边界,\(h_{1,j}\) 亦然。不过 \(h\) 关于 \(j\) 不具备单调性,在线维护 \(h_{0,j}+h_{1,j}\) 似乎有点困难。

然而 \(j\) 在数据结构中属于“自定义维度”,没有实际意义,通常不以它为轴。分析有效转移边,对于 \((h_{0,j},h_{1,j},g_j)\),取 \((h_{0,j'},h_{1,j'},g_{j'})\),若前者有效,则必有 \(g_j\ge g_{j'}\) 且不满足 \(g_j=g_{j'},h_{0,j}\ge h_{0,j'},h_{1,j}\ge h_{1,j'}\)。换句话说只保留 \(g_j\) 最大且 \(h_{1,j}\) 关于 \(h_{0,j}\) 为前缀最小值的元素即可,有效元素的 \(h_{1,j}\) 轴关于 \(h_{0,j}\) 轴有单调性,做到 \(O(n\log n)\)

posted @ 2026-05-18 17:33  timefinder  阅读(5)  评论(0)    收藏  举报