◊ \Large{\color{red}\Diamond} ◊ 为重点转换步骤。
感觉像是几个套路拼在一起的缝合题目,但我好像都无法快速识别。
先将这条数轴拉成一个平面图,x 轴是数轴,y 轴是时间,有左右边界 x = 0 x=0 x = 0 和 x = m x=m x = m ,那么 Jerry 需要从 ( 0 , x ) (0,x) ( 0 , x ) 到 ( + inf , x ′ ) (+\inf,x') ( + inf , x ′ ) ,而 Tom 需要通过若干条 ( a i , t i ) → ( b i , t i + ∣ b i − a i ∣ ) (a_i,t_i) \to (b_i,t_i+|b_i-a_i|) ( a i , t i ) → ( b i , t i + ∣ b i − a i ∣ ) 的线段将这个平面图割开使 Jerry 无法通过。◊ \Large{\color{red}\Diamond} ◊
Tom 的线段都是斜率为 ± 1 \pm 1 ± 1 的,Jerry 移动的斜率为 [ − 1 , 1 ] [-1,1] [ − 1 , 1 ] ,考虑将这个图顺时针旋转 45 ° 45\degree 4 5 ° 并扩大 2 \sqrt2 2 倍(即将点 ( x , y ) → ( x + y , y − x ) (x,y) \to (x+y,y-x) ( x , y ) → ( x + y , y − x ) ),左右边界变成 y = x y=x y = x 和 y = x − 2 m y=x-2m y = x − 2 m 。机器猫变成使用水平和竖直的线段将左右边界断开,有两种方式:
一条水平和竖直线段直接相交,阻止 Jerry 通过。
因为 Jerry 旋转后只能向右上(包含右和上)移动,所以可以使用两条不相交的线将 Jerry 的 x/y 坐标限制在一个区间中(如下图中红色线段是机器猫的不相交限制线段,Jerry 可以走绿色的路径,但到达了 ? 后就无法继续走)。

考虑刻画这样的限制,对于每条竖线,令上面的点是 in,下面的是 out,横线左边的是 in,右边的是 out。可以发现对于两种方式都能用以下方式刻画:i n x → o u t x in_x \to out_x i n x → o u t x ,对于满足 i n x in_x i n x 在 o u t y out_y o u t y 左上角的点连接 o u t y → i n x out_y \to in_x o u t y → i n x 。◊ \Large{\color{red}\Diamond} ◊ 若最后能从在 y = x y=x y = x 的点到达 y = x − 2 m y=x-2m y = x − 2 m 的点,则经过的边的长度和就是 k = 1 k=1 k = 1 时的答案。
继续拓展到 k > 1 k>1 k > 1 的情况,要选出 k k k 条不相交的,可以构建费用流模型 ◊ \Large{\color{red}\Diamond} ◊
将 S S S 连向所有在 y = x y=x y = x 上的点,容量为 1 1 1 ,费用为 0 0 0 。
i n x → o u t x in_x\to out_x i n x → o u t x 容量为 1 1 1 ,费用为 w x w_x w x 。
o u t y → i n x out_y\to in_x o u t y → i n x 容量为 + ∞ / k +\infty / k + ∞ / k ,费用为 0 0 0 。
将所有在 y = x − 2 m y=x-2m y = x − 2 m 上的点连向 T T T ,容量为 1 1 1 ,费用为 0 0 0 。
答案就是这个图在流量为 k k k 时的最小费用。注意 1 1 1 和 4 4 4 的容量不是 + ∞ / k +\infty/k + ∞ / k 是因为若在这个点重合时,Jerry 直接走到这个点只需要扣 1 1 1 的血量,而 3 3 3 是因为这条边只是虚构的边,实际画一下可以发现 Jerry 至少会扣两滴血量。
但是现在还是有 O ( n 2 ) \mathcal O(n^2) O ( n 2 ) 条边,考虑优化建图,每个 o u t out o u t 向左上角的 i n in i n 连边,显然是一个二维偏序关系,使用主席树/可持久化树状数组优化即可。因为 f l o w flow f l o w 很小,使用原始对偶求费用流最后复杂度为 O ( n k log 2 n ) \mathcal O(nk\log^2n) O ( n k log 2 n ) 。
好像应该之前讲过,但当时不会轮廓线 dp 就没改。
列出一个 m × n m\times n m × n 的矩阵,其中 G i , j G_{i,j} G i , j 表示第 i i i 天机场 j j j 剩余的行李数量。不难建出网络流模型:
( i , j ) → ( i + 1 , j − 1 ) (i,j) \to (i+1,j-1) ( i , j ) → ( i + 1 , j − 1 ) ,容量为 a i , j a_{i,j} a i , j 。
( i , j ) → ( i + 1 , j ) (i,j)\to (i+1,j) ( i , j ) → ( i + 1 , j ) ,容量为 b i , j b_{i,j} b i , j 。
( i , j ) → ( i + 1 , j + 1 ) (i,j)\to (i+1,j+1) ( i , j ) → ( i + 1 , j + 1 ) ,容量为 c i , j c_{i,j} c i , j 。
S → ( 1 , i ) S\to(1,i) S → ( 1 , i ) ,容量为 s i s_i s i 。
( k , i ) → T (k,i)\to T ( k , i ) → T ,容量为 + ∞ +\infty + ∞ 。
第 k k k 天的答案就是最大流,直接做复杂度是 O ( n m 3 ) \mathcal O(nm^3) O ( n m 3 ) ,无法通过。
考虑 n n n 很小时的做法,因为最大流 = 最小割,所以可以考虑维护 n n n 个点到 S S S 的连通性来计算最小割。记 f i , j , S , 0 / 1 f_{i,j,S,0/1} f i , j , S , 0 / 1 表示前 i i i 行,目前到达 j j j ,( i , [ 1 , j ) (i,[1,j) ( i , [ 1 , j ) 和 ( i − 1 , [ j , n ] ) (i-1,[j,n]) ( i − 1 , [ j , n ] ) 的连通状态为 S S S ,( i , j ) (i,j) ( i , j ) 是否连通 S S S 的最小割。用轮廓线 dp 不难做到 O ( n m 2 n ) \mathcal O(nm2^n) O ( n m 2 n ) 。
有结论:∑ i = 1 m ∑ j = 1 n [ c i , j > 0 ] = O ( L 4 3 ) \sum_{i=1}^m\sum_{j=1}^n [c_{i,j}>0]=\mathcal O(L^\frac43) ∑ i = 1 m ∑ j = 1 n [ c i , j > 0 ] = O ( L 3 4 ) ,其中 c i , j c_{i,j} c i , j 表示 s j s_j s j 匹配 t i t_i t i 的次数。证明:
所以若将 t i t_i t i 放入 s s s 构建的 AC 自动机中跑,只在成功匹配的 t t t 中计数是能够接受的。建出一棵 e n d end e n d 树,f a x → x fa_x \to x f a x → x 表示 e n d p o s ( s f a x ) endpos(s_{fa_x}) e n d p o s ( s f a x ) 是 e n d p o s ( s x ) endpos(s_x) e n d p o s ( s x ) 在 fail 树上最深的终点的祖先。对于每次询问 t t t ,将 t t t 在 AC 自动机上匹配的 e n d p o s endpos e n d p o s 集合 S S S 的所有点在 e n d end e n d 树中暴力 dfs 子树并贡献答案即可,复杂度为 O ( L 4 3 ) \mathcal O(L^\frac43) O ( L 3 4 ) 。
直接暴力 dfs 常数比较大,可以类似按照拓扑序,从原来加边的地方改成维护从下到上的链,常数较小可以通过。
最长公共子串考虑 SA。不难发现答案就是求 max i = l r min ( r − i + 1 , l c p ( s u f S i , s u f T j ) ) \displaystyle\max_{i=l}^r\min(r-i+1,lcp(sufS_i,sufT_j)) i = l max r min ( r − i + 1 , l c p ( s u f S i , s u f T j ) ) 。先把 S + # + T S+\#+T S + # + T 拼起来,然后对于固定的 i i i ,l c p ( s u f S i , s u f T j ) lcp(sufS_i,sufT_j) l c p ( s u f S i , s u f T j ) 的最大值就是找 r k j rk_j r k j 距离 r k i rk_i r k i 最近的属于 T T T 的 j j j ,只用找前面和后面即可。然后处理对 r − i + 1 r-i+1 r − i + 1 的限制,可以直接二分答案 x x x ,然后在 [ l , r − x + 1 ] [l,r-x+1] [ l , r − x + 1 ] 中寻找最大的 l c p ( s u f S i , s u f T j ) lcp(sufS_i,sufT_j) l c p ( s u f S i , s u f T j ) 即可。复杂度为 O ( n log n + q log n ) \mathcal O(n\log n+q\log n) O ( n log n + q log n ) 。
OGF 入门题
给定 n n n 和 m m m ,你需要计数长度为 n n n 的序列,每个数是 1 , 2 , 3 , 4 1,2,3,4 1 , 2 , 3 , 4 之一,满足 1 1 1 的数量减 2 2 2 的数量等于 m m m 。
f i , j = ∑ f i − 1 , j − 1 + f i − 1 , j + 1 + 2 f i − 1 , j , f 0 , i = 0 F i ( x ) = F i − 1 ( x ) ( x + 1 x + 2 ) F n ( x ) = ( x + 1 x + 2 ) n a n s = [ m ] ( x 2 + 2 x + 1 x ) n a n s = [ n + m ] ( x + 1 ) 2 n a n s = [ n + m ] ∑ i = 0 2 n ( 2 n i ) x i a n s = ( 2 n n + m ) f_{i,j}=\sum f_{i-1,j-1}+f_{i-1,j+1}+2f_{i-1,j},f_{0,i}=0 \\
F_i(x)=F_{i-1}(x)(x+\frac 1x+2) \\
F_n(x)=(x+\frac 1x+2)^n\\
ans=[m](\frac{x^2+2x+1}x)^n\\
ans=[n+m](x+1)^{2n} \\
ans=[n+m]\sum_{i=0}^{2n} \binom{2n}i x^i\\
ans=\binom{2n}{n+m}
f i , j = ∑ f i − 1 , j − 1 + f i − 1 , j + 1 + 2 f i − 1 , j , f 0 , i = 0 F i ( x ) = F i − 1 ( x ) ( x + x 1 + 2 ) F n ( x ) = ( x + x 1 + 2 ) n a n s = [ m ] ( x x 2 + 2 x + 1 ) n a n s = [ n + m ] ( x + 1 ) 2 n a n s = [ n + m ] i = 0 ∑ 2 n ( i 2 n ) x i a n s = ( n + m 2 n )
考虑拆开 v a l ( T ) val(T) v a l ( T ) :
v a l ( T ) = ( ∑ i = 1 n − 1 w i ) × gcd ( w 1 , w 2 , … , w n − 1 ) = ( ∑ i = 1 n − 1 w i ) × ∑ d ∣ w 1 , d ∣ w 2 , … d ∣ w n − 1 φ ( d ) = ∑ d φ ( d ) [ d ∣ w 1 ∧ ⋯ ∧ d ∣ w n − 1 ] ∑ i = 1 n − 1 w i val(T)=(\sum_{i=1}^{n-1}w_i)\times \gcd(w_1,w_2,\dots,w_{n-1})\\
=(\sum_{i=1}^{n-1}w_i)\times \sum_{d|w_1,d|w_2,\dots d|w_{n-1}} \varphi(d) \\
=\sum_d \varphi(d)[d|w_1\wedge\dots\wedge d|w_{n-1}]\sum_{i=1}^{n-1}w_i\\
v a l ( T ) = ( i = 1 ∑ n − 1 w i ) × g cd( w 1 , w 2 , … , w n − 1 ) = ( i = 1 ∑ n − 1 w i ) × d ∣ w 1 , d ∣ w 2 , … d ∣ w n − 1 ∑ φ ( d ) = d ∑ φ ( d ) [ d ∣ w 1 ∧ ⋯ ∧ d ∣ w n − 1 ] i = 1 ∑ n − 1 w i
将 d d d 的倍数的边拉出来做 Matrix-Tree 即可,但是还有问题就是矩阵树定理求解的是 w i w_i w i 的积的和,但我们需要求 w i w_i w i 的和。实际上 Matrix-Tree 的权值 w i w_i w i 不一定是常数,还可以是函数,所以将 w i ′ = w i x + 1 w'_i=w_ix+1 w i ′ = w i x + 1 ,这样求出来的函数的一次项就是答案了◊ \Large{\color{red}\Diamond} ◊ 。做的过程只需要记录一次项和常数项即可,复杂度为 O ( V n 3 ) \mathcal O(Vn^3) O ( V n 3 ) ,实际上准确的上界是 O ( n max d ( V ) n 3 ) \mathcal O(n\max d(V)n^3) O ( n max d ( V ) n 3 ) ,可以通过。
精妙的转化,积累一下套路。
首先不难发现可以在 max a i \max a_i max a i 处断开,完成断环成链,移动至 a 1 = max a i a_1=\max a_i a 1 = max a i 。令 f i f_i f i 表示目前在 i i i 的期望收益,不难列出方程f i = max ( a i , f i − 1 + f i + 1 2 − b i ) f_i=\max(a_i,\frac{f_{i-1}+f_{i+1}}2-b_i) f i = max ( a i , 2 f i − 1 + f i + 1 − b i ) 。尝试将 b i b_i b i 提出来做常数项,构造 g i = f i + d i ◊ g_i=f_i+d_i\Large{\color{red}\Diamond} g i = f i + d i ◊ 。
g i = max ( a i , f i − 1 + f i + 1 2 − b i ) + d i g i = max ( a i + d i , g i − 1 − d i − 1 + g i + 1 − d i + 1 2 − b i + d i ) g i = max ( a i + d i , g i − 1 + g i + 1 2 − d i − 1 + d i + 1 − 2 d i + 2 b i 2 ) g_i=\max(a_i,\frac{f_{i-1}+f_{i+1}}2-b_i)+d_i \\
g_i=\max(a_i+d_i,\frac{g_{i-1}-d_{i-1}+g_{i+1}-d_{i+1}}2-b_i+d_i)\\
g_i=\max(a_i+d_i,\frac{g_{i-1}+g_{i+1}}2-\frac{d_{i-1}+d_{i+1}-2d_i+2b_i}2)\\
g i = max ( a i , 2 f i − 1 + f i + 1 − b i ) + d i g i = max ( a i + d i , 2 g i − 1 − d i − 1 + g i + 1 − d i + 1 − b i + d i ) g i = max ( a i + d i , 2 g i − 1 + g i + 1 − 2 d i − 1 + d i + 1 − 2 d i + 2 b i )
因为要让 max \max max 后半部分的常数剔除,所以构造 d i − 1 + d i + 1 − 2 d i + 2 b i = 0 d_{i-1}+d_{i+1}-2d_i+2b_i=0 d i − 1 + d i + 1 − 2 d i + 2 b i = 0 ,即 d i = − 2 b i − 1 + 2 d i − 1 − d i − 2 d_i=-2b_{i-1}+2d_{i-1}-d_{i-2} d i = − 2 b i − 1 + 2 d i − 1 − d i − 2 ,初始项随便设成 d 0 = d 1 = 0 d_0=d_1=0 d 0 = d 1 = 0 即可。
g i = max ( a i + d i , g i − 1 + g i + 1 2 ) g_i=\max(a_i+d_i,\frac{g_{i-1}+g_{i+1}}2)
g i = max ( a i + d i , 2 g i − 1 + g i + 1 )
a i + d i a_i+d_i a i + d i 已经是常数了,考虑后面是一个类似取中点的形式,若将点 ( i , g i ) (i,g_i) ( i , g i ) 放到坐标系中,取后面的部分代表了 i − 1 , i , i + 1 i-1,i,i+1 i − 1 , i , i + 1 三点共线。但加上和常数取 max \max max 时,发现会将 i i i 的点往上提,会形成一个类似凸包的形态◊ \Large{\color{red}\Diamond} ◊ 。具体证明大概是 2 g i ≥ g i − 1 + g i + 1 2g_i\ge g_{i-1}+g_{i+1} 2 g i ≥ g i − 1 + g i + 1 ,即 g i − g i − 1 ≥ g i + 1 − g i g_i-g_{i-1}\ge g_{i+1}-g_i g i − g i − 1 ≥ g i + 1 − g i ,所以会形成一个下凸壳,注意有 a n + 1 = a 1 a_{n+1}=a_1 a n + 1 = a 1 。
好像依旧不太会 Slope Trick /ll
记 S i S_i S i 表示在 i i i 时刻的烟花的位置集合,f i , j f_{i,j} f i , j 表示前 i i i 时刻在 j j j 的答案,不难列出 f i , j = min k = 1 j f i − 1 , k + ∑ x ∈ S i ∣ j − x ∣ f_{i,j}=\min_{k=1}^j f_{i-1,k}+\sum_{x\in S_i}|j-x| f i , j = min k = 1 j f i − 1 , k + ∑ x ∈ S i ∣ j − x ∣ 。后面的 ∑ \sum ∑ 部分显然是下凸函数,然后可以归纳证明 F i ( x ) = f i , j F_i(x)=f_{i,j} F i ( x ) = f i , j 也是下凸函数,考虑使用 Slope Trick。◊ \Large{\color{red}\Diamond} ◊
使用堆维护斜率拐点(经过堆中的拐点时斜率会 − 1 -1 − 1 ),因为需要做前缀取 min \min min ,即将所有的斜率和 0 0 0 取 min \min min ,考虑倒着维护从右往左的拐点。直接记录 k , b k,b k , b 表示在 + ∞ +\infty + ∞ 处的 F ( x ) = k x + b F(x)=kx+b F ( x ) = k x + b ,当加入 ∣ x − p ∣ |x-p| ∣ x − p ∣ 函数时,在 x ≥ p x\ge p x ≥ p 时会 k ← k + 1 , b ← b − p k\gets k+1,b\gets b-p k ← k + 1 , b ← b − p ,到了 p p p 处时还原成 p − x p-x p − x ,即设置两个在 p p p 处的拐点时 k ← k − 2 , b ← b + 2 p k\gets k-2,b\gets b+2p k ← k − 2 , b ← b + 2 p 。
做完了加凸函数,然后再前缀取 min \min min ,直接从右往左走直到 k ≤ 0 k\le 0 k ≤ 0 时即可。复杂度 O ( n log n ) \mathcal O(n\log n) O ( n log n ) 。代码很好写,但理解了挺久的。