《浅谈杨氏矩阵在信息学竞赛中的应用》 - 学习笔记
定义跳过。
3 杨表和排列的对应关系
插入算法: \(S\gets x\) 表示把 \(x\) 从第一行插入 \(S\) 中,每次找到该行的 upper_bound
,用 \(x\) 替换,然后往下插入。如果找不到就直接插在末尾。
\(x\to S\) 表示从第一列插入,方法类似。
删除算法:删掉位置 \((i,j)\) ,把从行插入算法倒过来做。
对于一个排列 \(X\) ,可以同时维护两个表 \(P_X,Q_X\) ,初始都为空。按顺序执行 \(P_X\gets x_i\) ,并把插入时加的那个格子在 \(Q_X\) 中的对应位置赋为 \(i\) 。那么最后 \(P_X,Q_X\) 都是杨表。
由于插入算法和删除算法互为逆操作,所以从一对形状相同的 \(P,Q\) 出发也可以造出一个排列,所以一一对应。
4 杨表和对称矩阵
一个矩阵 \(A\) 可以对应到一些数对 \((i,j)\) ,其中 \((i,j)\) 出现了 \(A_{i,j}\) 次。把这些数对排序,可以得到一些 \((u_i,v_i)\) 。
然后按顺序往 \(P\) 中插入 \(v_i\) ,并在 \(Q\) 中记录 \(u_i\) ,可以得到一对半标准杨表。可以发现一对形状相同的半标准杨表也同样可以对应回一组 \((u,v)\) (在 \(Q\) 中找到最大值所在的那一堆格子,找到在 \(P\) 中对应的最大值的格子(若仍有多个,一定是在同一行,就找最右边的那个),把它删掉)。
现在考虑 \(P,Q\) 里面具体存了什么。先考虑第一行。
也就是每次找到所有 \(v\) 的(严格)前缀最小值作为 \(A_X^{(1)}\) ,然后删掉并重复。可以发现 \(A_X^{(1)}\) 就是曾经在 \(P_X^{(1,1)}\) 出现过的所有数。 \(P\) 的第一行是取每个 \(A_X^{(i)}\) 中的最小的,而 \(Q\) 的第一行是取最大的。注意这里只说了第一行而没说下面。
不是很想看证明……
简单感性证明一下 \(u,v\) 是排列时为什么第一行是对的:此时 \(P\) 的第一行存的是满足“以它结尾的 LIS 长度为 \(i\) ”的最小的 \(v\) ,而 \(Q\) 的第一行存的是“到哪里时第一次得到长度为 \(i\) 的 LIS ”。把 \((u,v)\) 取反得到 \((u,v^{-1})\) (注意 \(u_i=i\) ),而 \(v\) 的一个 LIS 也可以对应到 \(v^{-1}\) 的一个 LIS ,所以大概就是对的了。
其他的用某种方法证明,不想看了。
剩下的也不想看了,我赌它不考。
5 杨表与最长上升子序列
定理: \(P_X\) 的第一行长度即为排列 \(X\) 的 LIS 长度。显然。
引理: \((x\to S)\gets y=x\to (S\gets y)\) 。你说是就是吧。
定理:对于排列 \(X\) 和杨表 \(P_X\) ,如果翻转 \(X\) 得到 \(X^R\) ,那么 \(P_{X^R}\) 即为 \(P\) 翻转行列得到。
证明:归纳法,用上面那个引理来交换插入顺序。
这个定理可以引出一些别的东西。比如由于 LIS 翻转之后就得到 LDS ,所以下文的 \(\text{k-LIS}\) 序列翻转就会得到 \(\text{k-LDS}\) 。把一整个排列翻转之后, \(P\) 也翻转了行列,所以这也说明了 \(\text{k-LDS}\) 就是前 \(k\) 行的长度加起来。
另外,如果令 \(x_i:=n-x_i+1\) ,即翻转了小于号的定义,那么 \(\text{k-LIS}\) 和 \(\text{k-LDS}\) 也互相交换,所以杨表的形态也会翻转行列。但是里面填的值会发生奇妙的变化。
定理: \(P_X\) 的第一列长度是 \(X\) 的 LDS 长度。
5.1 最长的 \(\text{k-LIS}\) 子序列
定义 \(\text{k-LIS}\) 子序列为 LIS 长度不超过 \(k\) 的序列,同理定义 \(\text{k-LDS}\) 。然后就突然发现前 \(k\) 列的长度总和就是最长的 \(\text{k-LIS}\) 长度。
引理:对于序列中三个连续的数 \(x, y,z\,(x < y < z)\),如果它们在序列中不是按照 \((x, y,z)(z, y, x)\) 出现的话,交换 \(x,z\) 后序列的最长 \(\text{k-LIS}\) 子序列长度不变。
证明:
只考虑 \((z,x,y)\to (x,z,y)\) ,另外三种情况他说是类似的那就类似吧。
显然交换之后答案不会变大,只需要证明答案不会变小。考虑现在的最长序列 \(G\) ,如果不同时包含 \(z,x\) 那就没啥事,如果同时包含 \(z,x,y\) 那也没啥事,只有在 \(G\) 包含 \(z,x\) ,不包含 \(y\) ,且
swap(z,x)
之后获得了同时包含 \(x,z\) 的长度为 \(k+1\) 的 LIS ,的时候,才会出事。此时直接往 \(G\) 中加入 \(y\) ,删去 \(x\) ,有可能出现包含 \(y\) 的长度为 \(k+1\) 的 LIS 吗?
图中出现了 \((b)-x-(k-a)\) 和 \((a)-z-(k-b-1)\) ,一定有一个大于 \(k\) ,所以 \(G\) 不合法,矛盾。
所以就得到了不包含 \(x\) 的 \(G'\) ,所以答案不会变小。
引理:对于排列 \(X\) 和它产生的杨表 \(P\) ,重组一个排列 \(X^*=(P_{m,1},\cdots,P_{m,\lambda_m},P_{m-1,1},\cdots,P_{1,\lambda_1})\) ,那么 \(X\) 可以通过上面那个引理的交换操作转化成 \(X^*\) 。
归纳法,每插入一个就在当前的排列里模拟一遍。
现在每一段最多选 \(\min(k,\lambda_i)\) 个,所以直接选前 \(k\) 列就顶到了上界,并且合法。
CTST2017 最长上升子序列
相当于是要维护每一个前缀的杨表,求出前 \(k\) 列的长度之和。
暴力做插入操作是 \(O(n^2\log n)\) 爆了。
注意到 \(k>\sqrt n\) 时每一列的长度不会超过 \(\sqrt n\) ,所以可以只维护前 \(\sqrt n\) 行和前 \(\sqrt n\) 列。
维护行很容易,怎么维护列呢?由于我们只关心形态,所以可以简单地把小于号变成大于号另外维护一个杨表,那么前 \(\sqrt n\) 行其实就是真正的前 \(\sqrt n\) 列。
5.2 LIS 计数
如果只关心一些 \(\text{LIS,LDS}\) 长度的信息,那么就直接枚举杨表形态即可,复杂度大约是 \(p(n)\) 。
至于怎么数一个形态的杨表有多少个,见下文。
6 杨表与钩子公式
设 \(\lambda=(\lambda_{1},\cdots,\lambda_m)\) 为 \(n\) 的一个整数拆分,设 \(h_{\lambda}(i,j)\) 表示 \((i,j)\) 正右边和正下方的格子数量。
先直接给出公式:
或者如果只用 \(\lambda\) 表达,那就是
下面这个式子为什么和上面相等呢? \(\prod_{i=1}^{m}\left(\lambda_{i}+m-i\right) !\) 这一部分是假装杨表是一个完整的长方形,所以每一行的贡献应当是 \({\left(\lambda_{i}+m-i\right) !}\over (m-i)!\) ;而上面则是把有缺口的位置的贡献除掉,并把多余的 \((m-i)!\) 除掉。
6.1 钩子公式的一个证明
采用归纳法。设 \(\lambda\) 是 \(n\) 的一个整数拆分,那么以它为形态的杨表中必须找到一个边角格子放 \(n\) ,而把这个 \(n\) 删去就会得到 \(n-1\) 的整数拆分 \(\mu\) 。记 \(\mu\to \lambda\) 当且仅当形状为 \(\lambda\) 的杨图包含形状为 \(\mu\) 的杨图,那么就要证明
先来冷静分析一下,删去一个边角格子会对 \(h\) 带来什么影响。显然不同行也不同列的 \(h\) 完全没有变化;在同一行中,它们的 \(h\) 全部减一,但是原来的 \(h\) 可能被分成了若干个连续段,每一段只有开头结尾没被抵消,所以只会在边角格子附近有变化。
设 \(c=(i,j),ct(c)=i-j\) 。下面是一个例子。
click to open
把 \(\lambda\) 的所有边角拿出来,设从上往下分别是 \(X_i=(\alpha_i,\beta_i)\,(1\le i\le m)\) 。令 \(Y_i=(\alpha_i,\beta_{i+1})\,(0\le i\le m)\) ,且 \(\alpha_0=\beta_{m+1}=\beta_0=0,X_0=(0,0)\) 。再设 \(A(c),B(c)\) 为 \(c\) 往下和往右走到最远的点,那么 \(h_{\lambda}(c)=ct(A(c))-ct(B(c))+1\) 。
下面是一个例子。
click to open
令 \(x_i=ct(X_i),y_i=ct(Y_i)\) ,那么显然有 \(\sum_{i=0}^m x_i=\sum_{i=0}^m y_i\) 。
接下来的证明分为三个步骤:
第一步
设 \(\mu^{(i)}\) 加上 \(X_i\) 得到 \(\lambda\) ,那么只有和 \(X_i\) 同行同列,且在边角格子旁边的格子才会有影响。对于同列的格子,设 \(L_j=(\alpha_j,\beta_i)\,(1\le j<i),M_j=(\alpha_j+1,\beta_i)\,(1\le j<i)\) ,那么只有它们才有贡献。有
同行的格子同理,懒得抄了。
所以
第二步
注意到分母的 \(\prod_{j\ne i}(x_i-x_j)\) 和拉格朗日插值有点神似,所以引入变量 \(t\) ,看插出来的多项式有什么性质。设
那么 \(P\) 是 \(m-1\) 次多项式,而要求的东西就是它的 \(m-1\) 次项系数。 \(Q\) 是 \(m+1\) 次多项式。注意到 \((P+Q)(x_i)=0\) ,且 \(x_i\) 互不相同,所以还存在一个 \(\alpha\) ,使得
而又因为 \(\sum x_i=\sum y_i\) ,且 \([t^m]P(t)=0\) ,所以 \(\alpha=0\) 。所以要求的即为
因为 \(x_0=0\) ,所以两个式子可以缩到一起。然后有两个变量 \(i,j\) 很不爽,用平方消掉。然后再用一次 \(\sum x_i=\sum y_i\) ,就得到了
第三步
考虑 \(x,y\) 具体是什么,直接带进去,化简,就可以得到 \(n\) 。
6.2 在杨图上的随机游走
背不下来,希望不考。
7 杨表与网格图路径
网格图路径就是从一个整点走到另一个整点,每一步都往上或往右,的路径。
7.2 非交叉网格路径
我对 LGV 引理的理解(谢谢 EI 太阳):
考虑任意一组从起点到终点(顺序任意)的路径,如果它们有交点,那么可以找到整张图中的第一个交点(小于号随便定义一下),然后把交于这里的路径的起点任意排列,那么奇排列和偶排列的个数恰好相等。
所以可以枚举任意排列之后的起点终点对应关系(也就是枚举一个排列),算出方案数,并根据奇偶性决定是否乘 -1 。这就是行列式的定义式。
于是所有有交的路径组合都被干掉了,而剩下的组合则乘上了 \(\text{sgn}(\sigma)\) 。由于起点终点的坐标大小关系,只有 \(\sigma=(1,2,\cdots,n)\) 的时候才有可能不交,所以就得到了答案。
然后是两个简单的一一对应关系:
半标准杨表 $\leftrightarrow $ \(\{(-i,1)\},\{(\lambda_i-i,n)\}\) 的不相交路径:
半标准斜杨表 \(\leftrightarrow\) \(\{(\mu_i-i,1)\},\{(\lambda_i-i,n)\}\) 的不相交路径:
7.3 行列式公式
由于上面两个对应关系,可以得到对(半)标准(斜)杨表的计数方法。半标准(斜)杨表可以直接对应到一组路径,所以计数方法显然;标准杨表已经有钩子公式;标准斜杨表则是在路径的基础上要求每个纵坐标只有一条路径往右走,但是这与 LGV 引理的容斥方式并不矛盾,所以可以得到
例(欧拉数):求长为 \(2n\) 的排列中,满足 \(a_{1}<a_{2}>a_{3}<\cdots>a_{2 n-1}<a_{2 n}\) 的个数。
直接造一个对应的斜杨表即可: \((2 n-1+2,2 n-2+2, \ldots, n+2) /(2 n-1,2 n-2, \ldots, n)\) 。
用这个思路可以去做一些其他关于大小关系的计数问题。
后面还有一些诡异的计数公式,暂时不看了。
半标准杨表的计数公式:设 \(n\) 为值域,那么个数是
或是
注意是枚举到 \(n\) 。 \(i>|\lambda|\) 时 \(\lambda_i=0\) 。