有个表叫杨表(上)

《浅谈杨氏矩阵在信息学竞赛中的应用 袁方舟》膜拜有感

前方高能,非战斗人员请撤离(都是很干的数学概念)

前言

杨表 (Young tableaux),又叫杨氏矩阵,是一个啥都能掺一脚的代数结构。

为了方便讨论,先来点定义。

杨图:令 (lambda = (lambda_1,lambda_2,ldots,lambda_m)) 满足 (lambda_1gelambda_2geldotslambda_mge 1,n=sum lambda_i)。一个形状为 (lambda) 的杨图是一个表格,第 (i) 行有 (lambda_i) 个方格,其坐标分别为 ((i,1)(i,2)ldots(i,lambda_i))。下图为 (n=9,lambda=(4,2,2,1)) 的杨图。

[left[egin{array}{c} * & * & * & * \ * & * \ * & * \ * end{array} ight] ]

半标准杨表:将杨图填上数字,满足每行数字单调不减,每列数字单调递增。

标准杨表:将 (1,2,ldots,n) 填入杨图,满足每行、每列数字单调递增。下图为 (n=9,lambda=(4,2,2,1)) 的一种标准杨表。

[left[egin{array}{c} 1 & 4 & 7 & 8 \ 2 & 5 \ 3 & 9 \ 6 end{array} ight] ]

斜杨图:令 (lambda = (lambda_1,lambda_2,ldots,lambda_m),mu=(mu_1,mu_2,ldots,mu_{m'})),则形状为 (lambda/mu) 的斜杨图为杨图 (lambda) 中扣去杨图 (mu) 后剩下的部分。下图为 ((9, 7, 5, 1)/(5, 3, 2)) 的斜杨图。

[left[egin{array}{c} cdot & cdot & cdot & cdot & cdot & * & * & * & * \ cdot & cdot & cdot & * & * & * & * \ cdot & cdot & * & * & * \ * end{array} ight] ]

斜半标准杨表、斜标准杨表:猜都猜得到,不浪费时间了。

杨表的插入操作 / RSK 算法

RSK 算法包括了插入和删除。删除操作其实就是插入反过来,不影响理解杨表就不写了。

想要插入 (x) 时,从第一行开始,在当前行中找最小的比 (x) 大的数字 (y) (upperbound)(其实大于 (x) 还是大于等于 (x) 要看具体情况),交换 (x,y),转到下一行继续操作;若所有数字比 (x) 小则把 (x) 放在该行末尾并退出(如果超出了杨图的行数,那么杨图行数加 (1)

举个 (alpha) 粒子,将 (3) 插入下图半标准杨表:

[left[egin{array}{c} 1 & 3 & 3 & 5 \ 2 & 6 \ 4 end{array} ight] egin{array}{c}leftarrow 3\\\end{array} ]

第一行找到 (5),变成:

[left[egin{array}{c} 1 & 3 & 3 & 3 \ 2 & 6 \ 4 end{array} ight] egin{array}{c}\leftarrow 5\\end{array} ]

第二行找到 (6),变成:

[left[egin{array}{c} 1 & 3 & 3 & 3 \ 2 & 5 \ 4 end{array} ight] egin{array}{c}\\leftarrow 6\end{array} ]

第三行找不到比 (6) 大的数字,放到末尾:

[left[egin{array}{c} 1 & 3 & 3 & 3 \ 2 & 5 \ 4 & 6 end{array} ight] ]

可以证明这样操作后仍然满足半标准杨表的定义。

上代码!

vector<int> a[N];
void insert(int x) {
	for (int i = 0;; i++) {
		auto it = upper_bound(a[i].begin(), a[i].end(), x);
		if (it == a[i].end()) {
			a[i].push_back(x);
			return;
		}
		swap(x, *it);
	}
}

杨表与 LIS

LIS (Longest Increasing Subsequence) 就是广为人知的最长上升子序列(有时是不下降)。杨表之所以能和 LIS 有关,是因为杨表的插入操作,只看其中一行的话,正好是 dp 求 LIS 的算法。(虽然这是废话)

拓展一下,如果要求 (k) 个不相交的 LIS,它们的长度之和最大为杨图前 (k) 行长度之和,即 (lambda_1+lambda_2+ldots+lambda_k)。不过要注意,杨表前 (k) 行并不能告诉我们 LIS 有哪些数。(类似 dp 求 LIS 后那个 dp 数组也无法告诉我们 LIS 有哪些数)

举个 (alpha) 粒子,如果把 ([1,5,3,2,6,7,4]) 插入到杨表中得到:

[left[egin{array}{c} 1 & 2 & 4 & 7 \ 3 & 6 \ 5 end{array} ight] ]

显然 (1,2,4,7) 不是 LIS,LIS 应该是 (1,5,6,7/1,3,6,7/1,2,6,7)。不过长度是相同的。

这题就是求 k-LIS 的题了。但是 (k) 没有限制,如果维护的杨表行数太大,朴素的插入算法 (O(n^2 log n)) 肯定过不了。这就需要一个杨表的性质:如果把比较运算反过来(大于变小于等于),插入操作后的杨图和原来的杨图是转置关系(但是杨表和杨表不是转置的,只是形状转置),具体可以看看这题的题解。

话说回来,由于杨表和转置杨表的关系,我们可以得出一个结论,如果杨表的第一行数字个数是最长上升子序列长度,那么第一列数字个数是最长不上升子序列长度。如果某题限制了最长上升子序列长为 (alpha),最长不上升子序列长为 (eta),我们就可以把它和行数为 (alpha),列数为 (eta) 的杨表联系起来。(现在还没用,一一对应的关系在下文会讲)

杨表与排列

我们可以将排列的数字按顺序插入到空杨表中,这样就会得到一个标准杨表。但是这会出现两个排列对应一个杨表的情况,比如排列 ([2,1,3]) 和排列 ([2,3,1]) 都会得到杨表 (left[egin{array}{c}1 & 3 \ 2 end{array} ight]),出大问题。

考虑一个排列对应两个杨表,每插入一个数字到杨表 (A),我们在杨表 (B) 对应位置记录这个数字的下标(下标从 (1) 开始)。

可以证明 (B) 也是个标准杨表。

举个 (alpha) 粒子,对于排列 ([2,3,1]),插入 (2) 得到:

[A=left[egin{array}{c}2 end{array} ight], B=left[egin{array}{c}1 end{array} ight] ]

插入 (3) 得到:

[A=left[egin{array}{c}2 & 3 end{array} ight], B=left[egin{array}{c}1 & 2 end{array} ight] ]

插入 (1) 得到:

[A=left[egin{array}{c}1 & 3 \ 2 end{array} ight], B=left[egin{array}{c}1 & 2 \ 3 end{array} ight] ]

([2,1,3]) 会得到:

[A=left[egin{array}{c}1 & 3 \ 2 end{array} ight], B=left[egin{array}{c}1 & 3 \ 2 end{array} ight] ]

这样,我们就把一个排列和两个标准杨表一一对应了起来。

杨表和对合排列

对合排列是一种特殊的排列,把对合排列当成个置换后,自己乘自己等于单位置换。好理解一点就是 a[a[i]]=i

比如 (left[egin{array}{c}1 & 2 & 3 \ 2 & 1 & 3end{array} ight]) 就是个对合置换。

为什么要讲对合排列呢,因为把对合排列对应的两个标准杨表是相等的。这意味着一个对合置换和一个杨表是一一对应的关系。

上篇只是个无聊的铺垫,在下篇中我会好好讲钩子公式和其他组合数学相关内容的。

下篇

原文地址:https://www.cnblogs.com/axiomofchoice/p/14360016.html