2025.10 做题记录
P2934 [USACO09JAN] Safe Travel G
首先根据经典结论,最短路跑完得出的有效边是一张 DAG,而题目中又保证了对于任意的 \(i\in [1,n]\),\(1\) 到 \(i\) 的最短路径都是唯一的,于是这张最短路 DAG 变成了所谓“最短路树”(虽然我忘了最短路树是不是这样的了但是他确实是一个树结构)。
题目的要求是 ban 掉 \(i\) 到它父亲的边并求出 \(1\) 到 \(i\) 的最短路。
Key Observation ban 掉这条边后最多经过一条非树边,且仅会经过一条非树边。
我们考察我们的路径应该长什么样子,首先是从根在根到 \(i\) 的路径上走一段距离,且不能超过 \(i\) 的父亲,然后沿着树边走到一个点 \(j\),从 \(j\) 走到最短路树上 \(i\) 的一个非严格儿子(可能是自己),然后沿着树边走到 \(i\)。
这个过程直接维护是不太简单的,我们考虑上面那个 Observation,对每条边进行贡献。具体的,每条非树边有两个端点 \(u\) 和 \(v\),路径长度可以表达为 \(len=\operatorname{dep}_v+w(u,v)+\operatorname{dep}_u-\operatorname{dep}_i\)。这些量我们都是知道的,于是这时候我们随便上个树剖也是可以维护的。
那么我们其实可以在树剖 \(O(n\log^2 n)\) 的基础上再进行优化。
Small Trick 我们可以把边排序然后把已经更新到最优状态的点用并查集缩起来,表示这些点已经被更新到最优状态,并不会再被更新了。这个有点像一种另类的树上 DSU,就是父亲更新完把儿子和父亲合并到同一集合即可。这样复杂度就被优化到了 \(O((n+m)\log n)\),即瓶颈在于最短路复杂度。
思想 考虑答案的形态,排除冗余的操作使得复杂度正确。
P5100 [JOI 2017 Final] 足球 / Soccer
略显诡异的思维题。
Key Observation 在最优策略下,一个人必定最多只能控球一次。这个很符合直觉,但是没有那么好证,这里也只给出一个感性的证明。具体来说,首先一个人肯定不会选择踢出去后自己捡球,因为无球跑步和带球跑的代价是相同的,那么踢出去捡球的代价为 \(Cx+Ax+B\),而自己直接带球跑的代价为 \(Cx\),这个显然更优。如果是队员 \(i\) 传给队员 \(j\),且队员 \(j\) 传一脚到一个位置离 \(i\) 最近,那请问传球的意义在哪儿,还不如不传 \(i\) 直接走到这个位置,算一下也只会徒增 \(A\) 和 \(B\)。
有了这个 Observation 就好办了。首先一个球落地,根据贪心策略一定是离球最近的这个人来捡球,且由上述说明,来捡球的这个人因为没有控过球所以还在原来的位置上,所以这个距离是一个定值,可以直接一遍 BFS 做出。接下来我们考虑对球的位置进行分层图最短路。
设 \(f_{i,j,0/1/2}\) 代表球在 \((i,j)\) 位置,球现在在地上或在东西方向上飞或在南北方向上飞的最小代价。这个没法 dp,但是我们可以图论建模。注意换方向飞必须先落地,然后我们可以把飞的 \(Ax+B\) 拆成 \(A+A+A+...+A+B\),这样就明晰多了,空中的边连 \(A\) 代价,空中到落地的转换连 \(B\) 代价,最后我们强制要求球落地即可。
思想 图论建模方法,调整法
P7214 [JOISC 2020] 治療計画
很难也很好的一题。我旨在使用另一种奇特的分析方法解释这道题。
首先根据分析答案形态的思想,先看看合法的治疗计划集合是怎样的。注意看一下一个在 \(t\) 时刻,区间为 \([l_i,r_i]\) 的治疗计划在 \(t+k\) 时刻的有效治疗区间就变成了 \([l_i+k,r_i-k]\),当然,除了 \(l_i=1\) 或 \(r_i=n\) 的情况。这些特殊的点就启发我们并不是按照治疗计划本身有什么顺序考虑,而是从 \(1\) 到 \(n\) 这个顺序考虑。
我们设 \(f_i\) 为治疗 \([1,i]\) 所需的最小代价,每次我们都有两种操作。
- 时间加 \(1\),\(i\) 变为 \(i-1\)。
- 加一个任意时间的治疗计划。讨论若 \(t_j<T\),则使得其生效区间的左端点 \(\leq i+1\),记其生效区间的右端点为 \(R_j\),此时 \(R_j\) 会缩小,特别的 \(R_j=n\) 不会缩小,若 \(R_j>i\),则 \(i\) 变为 \(R_j\),并且代价加 \(C_j\)。若 \(t_j\geq T\),记其生效区间的右端点为 \(R_j\),此时 \(R_j\) 不变,\(i\) 会随着第一种操作逐渐缩小,变为 \(i'\),若其生效区间的左端点 \(\leq i'+1\),若 \(R_j>i\),则 \(i\) 变为 \(R_j\),并且代价加 \(C_j\)。
上述是以 dp 的思想考虑答案的形式,但是我们不可能维护这么一个复杂的 dp,我们模拟一下 dp 在干什么之后发现,两个操作实际上可以统一为一个图论建模的形式,即若 \(|t_i-t_j|\leq r_i-l_j\),则 \(i\) 向 \(j\) 连一条长为 \(C_j\) 的边。这样就自然的想到了 \(O(n^2\log n)\) 的 dij 做法。
那么进入正确的道路上之后,我们的问题就在于如何强行优化这个 dij。
Important Trick 点权 dij 每个点仅会入队一次
这是个相当常用的 Trick,只不过我以前不知道。有了这个 Trick 之后,用优先队列维护也是顶困难的,但是我们知道最短路是可以使用线段树优化的,于是我们对着这个做。
具体的,我们先看看,区间限制是怎样的。先把绝对值拆了,改为:
- \(t_i-r_i\leq t_j-l_j(t_i<t_j)\)
- \(t_j+l_j\leq r_i+t_i(t_i\geq t_j)\)
那么我们先把治疗计划按照 \(t\) 排序,这样我们就把 \(t\) 的偏序关系改为了序列上的偏序关系。
注意到上面那些东西都是定值。对于每个点,我们寻找它后继的时候使用线段树查找,由于每个点仅会入队一次,所以入队后我们直接把这个点 ban 了,于是最后算法呈现出的就是一个势能线段树的形式。
思想 dp 思想,考虑答案形态,图论建模,线段树优化最短路
CF997E Good Subsegments
套路题,学一下时间线段树维护历史最小值个数的 Trick(数 \(0\) 线段树),注意这个线段树只在对于每一步,最小值都 \(\geq\) 的情况下可以使用。
显然的,把条件转化为 \(\max-\min-r+l=0\),并改成 \(\max-\min+l=r\),对 \(r\) 扫描线。\(\max\) 和 \(\min\) 套路的考虑单调栈维护将其变为一个矩形。
接下来我们的操作变为区间加,单点改,历史数 \(0\)。
考虑维护两个标记,一个正常的 \(\text{addtag}\),还有一个 \(\text{timtag}\),代表贡献次数。每扫到一个 \(r\),判断全局最小值是否为 \(r\),是的话 \(\text{timtag}_1\) 加 \(1\),贡献加上 \(\text{mincnt}_1\)。
注意下传标记的方式,假设要下传到左儿子,显然先下传 \(\text{addtag}\),然后若此时左儿子最小值等于父亲最小值,那么 \(\text{timtag}_{lc}=\text{timtag}_{lc}+\text{timtag}_{u}\)。贡献是 \(\text{timtag}_{u}\times \text{mincnt}_u\)。具体为什么可以复习时候想想,至少我现在知道为什么,但是很难表述出来。
P4786 [BalkanOI 2018] Election
质量挺高。
首先题目是一个类似括号序列的东西,显然的设 \(\text{C}\) 为 \(+1\),\(\text{T}\) 为 \(-1\)。然后要求任意前缀和非负,任意后缀和非负。
\(\text{Step 1}\space O(nq)\)
如果只要求前缀和非负,那么那么非常简单,设 \(pre_i\) 为 \(i\) 的前缀和,从前往后扫,若 \(pre_i=-1\),那么删除这个位置,同时后面的东西都 \(+1\),注意到这个操作把 \(-k\) 变为了 \(-(k-1)\),并消除了所有 \(-1\)。
由于对于后缀和来说先删后面的 \(-1\) 肯定更优,而对于刚才那个贪心,采取的是一种惰性删除方式,与后缀和的要求吻合,于是前缀和删完的形态对于后缀来说依然是最优形态。那么设改变后的序列的后缀和为 \(suf_i\),执行和前缀一样的操作即可。
\(\text{Step 2}\space O(q\log n)\)
一样的先只考虑前缀,仔细看会发现答案是固定的,即 \(-\min\{pre_i\}\),具体推导过程见上,设 \(-\min\{pre_i\}\) 为 \(-pre_{min}\)。那么麻烦的在于后缀,因为前缀的修改对后缀有影响,我们记未修改前的后缀为 \(suf_i\),修改后为 \(Suf_i\)(注意这里下标是一一对应的,因为删掉可以看作把一位改为 \(0\))。那么答案为 \(-Suf_{min}-pre_{min}\)。考虑 \(Suf_i\) 的形式,我们继续模拟贪心,可以知道 \(Suf_i\) 会变为 \(suf_i+\min\{pre_j(j<i)\}-pre_{min}\)。现在整合答案为 \(-suf_i-\min\{pre_j(j<i)\}+pre_{min}-pre_{min}=-suf_i-\min\{pre_j(j<i)\}\)。即两段不相交的前后缀和的最小值。
这个是不好 PushUp 的,改成最大子段和减去区间和线段树维护即可。
P11844 [USACO25FEB] Friendship Editing G
感觉这个题确实不错。
题目说若 \(a\) 和 \(b\) 之间有边,则对于任意的 \(c\),要么 \(a\) 和 \(c\) 之间有边,要么 \(b\) 和 \(c\) 之间有边。那这个逻辑关系太难刻画了,但是好在这个逻辑关系是一个基本的条件逻辑关系,非常便于转化,我们考虑写出其等价的逆否命题。
即:若存在 \(c\) 使得 \(a\) 和 \(c\) 之间没边,且 \(b\) 和 \(c\) 之间没边,则 \(a\) 和 \(b\) 之间没边。那都是没边看着太别扭了,我们自然地想到建出原图的反图,把条件改为:在原图反图上,若存在 \(c\) 使得 \(a\) 和 \(c\) 之间有边,且 \(b\) 和 \(c\) 之间有边,则 \(a\) 和 \(b\) 之间有边。
接下来我们来考虑能不能根据这个条件增量构造出这个图。现在考虑此时为 \(n=1\),我现在加入一个点想让两个点连通,显然两个点之间必然有边。那么 \(n=2\) 时,再加入一个点,随意选取一个点使其与加入点连通,那么由于其内部两点连通,根据条件,必然有新加入点也与另一个点连通,此时原图为 \(K_3\)。再加入一个点时,我们随机选取一个点,因为原图为 \(K_3\),所以必然保证我们选的这个点与所有点都有连边,那么根据条件,新加入点应与所有点都连边,现在图变为 \(K_4\)。以此类推可以得到其反图的每个连通块必然是一个完全图。换句话说,原图反图是多个完全图的并。
由于团问题非常难以有多项式复杂度做法,且数据范围为 \(n\leq 16\),我们来考虑状压 dp。记 \(h_S\) 为 \(S\) 集合构成的反图完全图至少需要改几条边。这里说一个常见的误区,就是你把原图改成反图之后,并没有改动任何边。接下来设 \(f_S\) 为让 \(S\) 集合构成完全图并的最小代价。显然有转移 \(f_S=f_T+f_{S-T}+w(S-T,T)\)。
\(w(i,j)\) 有两种求法:
- 递推法,但是这个要求空间 \(3^n\) 于是爆了。具体就是设 \(g_{S,T}\) 代表 \(S\) 和 \(T\) 之间的边数。然后 \(g_{S,T}=g_{S-\text{lowbit}(S),T}+|G(\text{lowbit}(S)) \cap T|\),其中 \(G(x)\) 代表 \(x\) 在反图上的邻居集合。这个可以注意到只会依赖 \(\text{popcount}-1\) 的集合,于是可以按 \(\text{popcount}\) 转移然后每次清空,这样空间不会爆,但是由于枚举无序,所以必须二分,这样时间会多 \(\log\),也爆了。
- 容斥法,我竟然没想到这个。设 \(l_{S}=\frac{|S|\times |S-1|}{2}-h_S\),则 \(w(S,T)=l_{S\cup T}-l_{S}-l_{T}\),这个空间是 \(2^n\) 的可以通过。
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号