原本以为这些都是些简单 trivial 的东西,并且一直没见过题,于是一直没学。直到 UNR D2T3 当头棒喝,发现自己其实啥也不会。
Itst Orz
学习自 psj APIO2021 讲课 《决策单调性与四边形不等式》。
昨天下午开始学习,在从广东到浙江的高铁上写了这篇 blog ,在宿舍里完工。希望能够 NOI2021 rp++;
如有错误请直接指出。我觉得我的思维非常不严谨……
定义什么的略过。(没有课件的可以随便找个群友要。)
需要非常注意的一点是,虽然下面经常会提到 \(n\times m\) 的矩阵,但矩阵内的元素都是可以直接计算的,而不需要输入。所以最后往往真正计算过的元素个数远小于 \(nm\) 。
可能需要一点时间才能适应这个想法。(或者是我太菜。)
另外,有的时候可能会把矩阵中的一些位置删掉,即强制不考虑这些位置。此时,只要剩下的位置满足四边形不等式(注意四边形不等式的条件仅仅是 \(i<j,u<v\) ,而对 \(j,u\) 没有限制),并且每一列剩下的位置是一个区间,并且这个区间的左右端点都单调递增,那么仍然可以证明行最小值位置的单调性。
拿出中间的一行,得到这一行的 \(\min\) ,然后切成两边。
复杂度 \(O(m\log n)\) 。
在原先的那篇 blog 里有较详细的介绍,这里不再赘述。
\(O(n+m)\) 计算完全单调矩阵的行最小值。课件中写的是 \(O(n+m(1+\max(0,\log{n\over m})))\) ,但是感觉这和线性确实没有区别?
思路很简单:行最小值的位置单调,那么我们只要确定所有偶数行的最小值位置,就可以 \(O(m)\) 把奇数行的最小值位置全部推出来。
但是如果无脑写那么复杂度是 \(O(n+m\log n)\) ,不行。
考虑复杂度瓶颈在哪。每次会把 \(n\) 折半,但是 \(m\) 并没有变化。当 \(n\) 很小的时候还有这么大的 \(m\) 就很浪费了。
所以引入 reduce 操作:给一个 \(n\times m\) 的完全单调矩阵,返回一个 \(n\times \min(n,m)\) 的子矩阵,包含所有行最小值。
只要能进行 reduce 操作,那么在 \(n\) 折半的时候 \(m\) 同样会变小,所以复杂度就变为上面那个样子了。
reduce 操作:
从左往右扫,维护所有可能包含行最小值的列。假设现在有 \(k\) 列,分别对应 \(1\sim k\) 行的最小值。
因为这样不会影响正确性,所以可以暂时认为对于 \(1\le i\le k,j>i\) ,有 \(A_{j,i}=+\infty\) ,即不考虑下三角的元素。
现在考虑第 \(k+1\) 列,比较 \(A_{k,k},A_{k,k+1}\) 。
- 如果 \(A_{k,k}< A_{k,k+1}\) ,那么第 \(k\) 列暂时没啥问题。如果 \(k\ne n\) 则把第 \(k+1\) 列加入, \(k\gets k+1\) ;否则第 \(k+1\) 列毫无用处,直接删掉。
- 否则第 \(k\) 列没有用,把第 \(k\) 列删除, \(k\gets k-1\) 。
有了 reduce 操作之后就可以每次让 \(n,m\) 同时折半了。
SMAWK 是离线算法,而 Wilber 算法可以处理某些在线的情况:
\[f_i=\min_{1\le j<i} f_j+w_{j,i} \]从左往右做,维护 \(r,c\) ,表示 \(1\le i\le c\) 的 \(f\) 已经确定,且 \(f_i\) 的转移点至少是 \(r\) 。
暂时不管后面未求出的 \(f\) ,直接用 \([r,c]\) 去估计后方的 \(f\) 。设 \(p=\min(n,c+(c-r+1))\) ,那么设 \(g_{[c+1,p]}\) 表示用 \([r,c]\) 得到的估计值。估计值用 SMAWK 算法得出。
\(g\) 当然是不够精确的,所以用 \(g_{[c+1,p]}\) 再次估计 \([c+1,p]\) 的 \(f\) ,设两次估计值的 \(\max\) 为 \(h\) 。
如果 \([c+1,p]\) 中都有 \(g=h\) ,那么说明这一段 \(f=g\) ,直接令 \(c=p\) 。
否则,找到第一个 \(t\) 使得 \(g_t\ne h_t\) ,则 \([c+1,t]\) 的 \(f=h\) ,且 \(t\) 的转移点 \(>c\) 。令 \(c'=t,r'=c+1\) 。
容易发现,我们每花 \(O(1)\) 的时间,就会让 \(c\) 和 \(c-r+1\) 增加 \(O(1)\) ,或者让 \(c-r+1\) 减小 \(O(1)\) 。所以总复杂度 \(O(n)\) 。
Wilber 算法在做“交错动态规划”时并不能使用:
\[\begin{aligned} f_{i} &=\min _{1 \leq j<i} g_{j}+w_{j, i} \\ g_{i} &=\min _{1 \leq j<i} f_{j}+w_{j, i}^{\prime} \end{aligned} \]原因在于 \(f,g\) 并不同步。可能 \(f\) 在第一次估计时就给出了正确值,但发现 \(g\) 在第二次估计时才估计正确,那么 \(f\) 的转移点可能还是很靠前,就比较麻烦。
然后就有 Eppstein 算法。
我们在下面主要考虑求 \(f\) ,但要注意 \(g\) 的计算也在同步进行。\(f,g\) 的 \(r,c,E\) 并不相同。
仍然维护 \(r,c\) ,表示 \(c\) 之后的可能从 \([r,c]\) 转移过来。但是另外记一个数组 \(E\) ,\(E_i\) 表示 \([1,c-1)\) 对 \(i\) 的贡献。
设 \(p=\min(n,c+(c-r+1))\) ,然后还是用 \([r,c]\) 的 \(g\) 估计 \([c+1,p]\) 的 \(f\) ,并与 \(E_{[c+1,p]}\) 取 \(\min\) ,得到 \(h\) 。
然后对于 \(c<i\le p\) 计算 \(v_i=\max_{i<j\le p}h_j-w_{i,j}\) ,表示如果 \(g_i< v_i\) 则会出现错误估计。
从 \(c+1\) 开始往右扫,设现在扫到 \(k\) 。
先令 \(f_k=h_k\) 。如果 \(g_k\ge v_k\) 那么无事发生,可以继续往后扫。
【否则用 \(h\) 更新 \(E_{[k+1,p]}\) ,并令 \(r'=c+1,c'=k\) 。】
这是很妙的一步:我们已经知道 \((k,p]\) 中有一个位置的转移点是 \(k\) ,所以 \((p,n]\) 的转移点都会在 \(k\) 之后。所以 \([r,k)\) 只能对 \((k,p]\) 产生贡献,记在 \(E\) 里面即可。
复杂度 \(O(n)\) 。
俗称石子合并
转移方程
\[f_{i, j}= \begin{cases}0, & i \geq j \\ w_{i, j}+\min _{i \leq k<j} f_{i, k}+f_{k+1, j} & i<j\end{cases} \]其中 \(w_{i,j}\) 满足四边形不等式,同时满足 \(l\le l'\le r'\le r\) 时有 \(w_{l,r}\ge w_{l',r'}\) 。
如果能证明 \(f_{i,j}\) 满足四边形不等式,那么就可以用经典方法把转移优化到 \(O(n^2)\) 。
设 \(f_{i,j}\) 的最优转移点(多个取最大的)是 \(K_{i,j}\) , \(f_{i,j}\) 在 \(k=y\) 时的转移值为 \(f_{i,j,y}\) 。
考虑 \(i\le j\le i'\le j'\) ( \(i'<j\) 的情况因为文章开始提到的原因可以忽略),我们希望证明 \(f_{i,i'}+f_{j,j'}\le f_{i,j'}+f_{j,i'}\) 。
如果 \(i=j\) 或 \(i'=j'\) 那么直接得证。
如果 \(j=i'\) ,那么其实是希望证明 \(f_{l,x}+f_{x,r}\le f_{l,r},l<x<r\) 。设 \(y=K_{l,r}\) ,并不妨假设 \(y< x\) 。此时直接把 \(f_{l,r}\) 爆拆成
\[f_{l,r}=w_{l,r}+f_{l,y}+f_{y+1,r}\ge w_{l,r}+f_{l,y}+f_{y+1,x}+f_{x,r}\ge f_{l,x}+f_{x,r} \]否则, \(i<j<i'<j'\) 。先把 \(w_{i,j'}+w_{j,i'}\) 放缩为 \(\ge w_{i,i'}+w_{j,j'}\) ,设 \(x=K_{j,i'},y=K_{i,j'}\) ,并不妨假设 \(x\le y\) 。此时可以把 \(f_{j,x}+f_{i,y}\) 放成 \(f_{i,x}+f_{j,y}\) ,然后和另外两个组合起来。
然后为了优化 DP ,需要证明 \(K_{i,j-1}\le K_{i,j}\le K_{i+1,j}\) 。固定 \(i\) ,设 \(a_{j,k}=f_{i,j,k}\) ,那么 \(a\) 是蒙日阵,且 \(K_{i,j}=\min_j a\) ,所以有单调性,左边的不等式得证。右边同理。
从二叉树变成 \(k\) 叉树,即把 1 个分界点变成 \(k-1\) 个分界点。
\(O(kn^2)\) 的做法非常显然。
注意到可以关于 \(k\) 这一维倍增,优化为 \(O(n^2\log k)\) 。
DAG ,边权为 \(w_{i,j}\) ,求 1 到 \(n\) 经过恰好 \(k\) 条边的最短路。
有简单的转移式:
\[f_{i, j}=\min _{1 \leq k<j} f_{i-1, k}+w_{k, j} \]当 \(w\) 没有性质的时候就没什么办法了。否则这个转移可以看做是对每个 \(j\) 求第 \(j\) 列的最小值,可以用 SMAWK 优化,总复杂度 \(O(nk)\) 。
但是在后面可以发现更好的性质。
XIX Open Cup Grand Prix of Zhejiang I. 环上邮局
\(n\) 个点放在一个长度为 \(L\) 的环上,把它们分成恰好 \(k\) 段,每段的代价是所有点到中位数的距离。求最小代价并输出方案。\(n,k\le 2.5\times 10^5\) 。
首先可以分析出代价函数具有四边形不等式:只需要按照内层中位数和外层中位数的位置关系分类讨论一下即可证明。
于是枚举在哪里断环为链,可以做到 \(O(n^2k)\) 。
进一步优化需要不少观察。
答案关于 \(K\) 下凸。
设 \(f(K)\) 为 \(K\) 的答案,这里直接证明对于 \(1\le s<r<t\le n-1,f(s)+f(t)\ge f(r)+f(s+t-r)\) 。
证明其实不难:把 \(f(s),f(t)\) 对应的路径画出来,一定可以找到 \(f(t)\) 的一条边 \((x,y)\) 被 \(f(s)\) 的一条边 \((u,v)\) 包含,即 \(u\le x<y\le v\) ,并且切换为 \((u,y),(x,v)\) 之后路径长度恰好变为 \(r,s+t-r\) 。稍微分析一下可以发现这样的两条边必然存在。
然后直接写个 wqs 二分就可以求出最小代价。然后用上面这个构造方法就可以构造出恰好 \(K\) 条边的方案。
复杂度 \(O(n^2\log V)\) 。
上面把 \((x,y),(u,v)\) 切换为 \((u,y),(x,v)\) 的操作还可以在很多地方运用。
定义一个路径的字典序:把经过的所有点丢进 \([0,L)\) 的范围中,再按此时的编号从小到大排序(即比较集合的字典序)。
定理:设 \(p_1=x_1,\cdots,x_{k+1}=q_1\) 为 \(p_1\) 到 \(q_1\) 的长度为 \(k\) 的字典序最小的最短路;设 \(p_2=y_1,\cdots,y_{k+1}=q_2\) 为 \(p_2\) 到 \(q_2\) 的长度为 \(k\) 的字典序最小的最短路。若 \(p_1\le p_2,q_1\le q_2\) ,则有 \(\forall i\in [1,k+1],x_i\le y_i\) 。
证明:
考虑 \(x_1\le y_1\) 且 \(x_{k+1}\le y_{k+1}\) ,所以如果能找到第一个 \(x_i>y_i\) 的位置,后面一定又可以找到第一个 \(x_j\le y_j\) 的位置。那么在 \(i\) 处的顺序是 \(x_{i-1},y_{i-1},y_i,x_i\) ,而 \(j\) 处的顺序则是 \(y_{j-1},x_{j-1},x_j,y_j\) 。分别改成交叉,路径长度和不变,而字典序发生了奇妙的变化。
定理:设 \(x_1,\cdots,x_{p+1}\) 为 \(f(p)\) 对应的字典序最小的最短路;设 \(y_1,\cdots,y_{p+2}\) 为 \(f(p+1)\) 对应的字典序最小的最短路。则有
\[y_1=x_1<y_2\le x_2\le y_3\le \cdots\le x_p\le y_{p+1}\le x_{p+1}=y_{p+2} \]证明:
把 \(y_1\sim y_{p+1}\) 和 \(y_2\sim y_{p+2}\) 分别拿出来和 \(x\) 用路径单调性的结论,即可把 \(y_i\) 限制在 \(x\) 的一个区间里。
回到 环上邮局 。
旋转环使得 \(0\) 处有一个点,从这里断开并倍长,跑一个 \(0\to L\) 的最小字典序 \(f(k)\) ,设路径是 \(0=x_1,\cdots,x_{k+1}=L\) 。
考虑全局最小字典序 \(f(k)\) ,设为 \(y_1,\cdots,y_{k+1}=y_1+L\) ,其中 \(0\le y_1,\cdots,y_k<L\) 。
由路径单调性,直接得到 \(y_i\ge x_i\) 。而截取 \(y_1,\cdots ,y_k\) 和 \(x_2,\cdots,x_{k+1}\) 用路径单调性,应该可以得到 \(y_i\le x_{i+1}\) 。
于是证明了 \(x\) 分成的每一段中恰好有一个 \(y\) 的点。因为一共有 \(k\) 段,所以段中点数最少的只有 \(n/k\) 个,可以只枚举这 \(n/k\) 个点的位置断环为链。于是复杂度被优化到 \(O(n^2)\) 。
其实到这里已经有点晕了,因为有点时候真的不太确定某个东西是不是最小字典序……
考虑 \(y_1\) 往右移动的时候(这时候 \(y\) 不一定是最优解),用路径单调性两个方向分析一下什么的,大概可以分析出每个 \(y_i\) 都在往右移动,并且仍然在 \(x\) 标出的段里。
那么对第一个区间分治,每次拿出中间的 \(y\) ,求出此时的最优解,然后把每一段都划分成两边……?
我最终第一个区间的每一个位置都还是要作为起点算一次,每次至少 \(O(k)\) ,所以这样还是 \(O(nk)\) 。
但是解决方法也很简单:把只有 \(n/k\) 的那个段拿出来做分治,此时复杂度就变成……?
反正是 \(O(n\text{ poly}(\log))\) ,不想分析了。
给出一个 \(n\times n\) 的蒙日阵,每个元素可以 \(O(1)\) 计算。\(q\) 次询问,每次问一个 \([l_1,r_1]\times [l_2,r_2]\) 矩形的最小值。
先分析 \(l_2=r_2\) ,即只询问一列的情况。对行建立线段树,对于一段行区间,每一列对应的最小值位置单调,并且可以被划分成 \(O(len)\) 个区间。记录这些区间,合并线段树两个子节点的时候二分分界点即可。这样预处理复杂度 \(O(n\log n)\) ,询问单次用分散层叠做到 \(O(\log n)\) 。
把矩阵转置之后对一行的询问也可以 \(O(\log n)\) 实现。
然后 \(l_2\ne r_2\) 的情况其实差不多,区间 \([l_2,r_2]\) 会对应 \(O(len)\) 个区间中的一些,以及一个前缀和一个后缀。前后缀暴力询问,完整的区间用树套树维护即可。
把点在 \([1,2n]\) 中编号。
对于 \(u<v<x<y<u+n\) ,因为交叉的性质,所以有 \(dis(u,x)+dis(v,y)\ge dis(u,y)+dis(v,x)\) 。
然后考虑标一些奇怪的值使得 \(v\ge x\) 或 \(y\ge u+n\) 的时候这个性质也成立。
对于 \(a,b\) ,如果 \(a\ge b\) 或者 \(a+n\le b\) 就 \(dis(a,b)=-\infty\) 。相当于对于一个 \(1\le a\le n\) ,只有 \((a,a+n)\) 中的值是有用的。
只保留这个区间之后仍然可以表示出两个点的 \(dis\) 。
虽然此时这个矩阵仍然不太满足四边形不等式(多个条件不合法的时候还是会暴毙),但是足够证明最大值位置的单调性了。
设现在的 \(dp\) 数组是 \(f_{i,x}\) ,其中 \(1\le x\le n\) 。那么给第 \(x\) 行加上 \(f_{i,x}\) 。(注意这里不能用列加,否则后面更新会带 2 倍常数)
从 \(f_i\) 转移到 \(f_{i+1}\) 时,基本上是 \(f_{i+1,x}=f_{i,x}+dis(P_i,P_{i+1})\) 。这就是整体加,很容易搞定。
麻烦一点的是 \(f_{i+1,P_i}\) 需要从 \(f_{i,x}+dis(x,P_{i+1})\) 转移过来。
这就是第 \(P_{i+1}\) 列和 \(P_{i+1}+n\) 列的最大值,直接得到。然后需要更新第 \(P_i\) 行,求出它们现在控制的区间。
二分往左往右扩展了多长即可。
操作次数 \(4q\log 2n+3q+O(1)\) 。
给定一个 \(n\times n\) 的蒙日阵 \(A\) ,且保证对角线元素为 0 ,作为带权有向图的邻接矩阵。求边权和最小的哈密顿回路。 \(n\le 10^6\) 。
我的垃圾做法:
假设从 \(i\) 跳到了 \(p_i\) ,那么就有 \(A_{i,p_i}\) 的贡献。把这些元素所在的位置标出来。
因为 \(A\) 是蒙日阵,所以任意交换 \(p\) 中的一个逆序对之后边权和都一定会减小。问题在于交换一个逆序对之后就从一个环变成了两个环。
但是考虑两个环可能可以通过再交换一次逆序对变回一个环,所以考虑什么时候这种情况可以发生。经过分析发现只要两个环包含的点不是分别对应一个前缀和一个后缀(即 \([1,i]\) 和 \([i+1,n]\) )就一定可以再交换一次合并成一个。
所以一定存在一个最优解 \(p\) 使得任意交换一个逆序对之后都可以被分成 \([1,i],[i+1,n]\) 两个环。
随机一些满足条件的 \(p\) ,看此时对应的路径长成什么样子。发现路径的样子必然是从 1 开始编号先上升到 \(n\) ,然后再下降回 1 。“双调回路”。
题解的牛逼做法:
对 \(n\) 归纳证明。找出一个不满足的位置 \(p\) , \(pre_p<p,suf_p<p\) ,则把 \(p\) 删掉,把剩下 \(n-1\) 个点的环调成双调回路,然后再找一个位置 \(q\) 使得 \(q<p<suf_q\) ,把 \(p\) 塞回去。
用四边形不等式证明每一步都不会变劣。
然后就只需要求权值和最大的双调回路了。
直接从左往右 DP ,记录当前这个位置是在上升还是下降,以及前面第一个与自己状态不同的点是哪个。无脑转移 \(O(n^2)\) ,而可以发现这个 DP 和 UOJ672 几乎一致,所以可以用一样的方法做到 \(O(n\log n)\) 。
把状态精简一下,设 \(F_i\) 表示 \(i+1\) 在下降, \(i\) 在上升的最小权值, \(G_i\) 对称。
列一下转移式,发现是交错型动态规划,并且转移的权值同样满足四边形不等式,于是可以 Eppstein 优化到 \(O(n)\) 。
不过 UOJ672 并不能这样优化,因为给出的点并不顺序,所以转移权值不再满足四边形不等式了。