「eJOI2022」LCS of Permutations 题解

题意

link:https://loj.ac/p/3888

给定 \(n,a,b,c\),构造大小为 \(n\) 的排列 \(p,q,r\) 满足 \(\operatorname{LCS}(p,q)=a,\operatorname{LCS}(p,r)=b,\operatorname{LCS}(q,r)=c\)

判断是否有解,可能要求构造方案。多组询问,\(\sum n\le 2\times10^5\)

题解

Anton 的神题就别考虑正解了。既然是 OI 题,那先去看部分分。

Subtask3 \(c=n\)

排列 \(q,r\) 是一样的,即构造两个 \(\operatorname{LCS}=a\) 的排列。

\(p\) 钦定成 \(1,2,\cdots,n\) 不影响答案。之后所有解法也这样考虑。

\(\operatorname{LIS}=a\) 的排列随便构造一下。

Subtask4 \(a=1\)

\(q\) 钦定成 \(n,n-1,\cdots,1\)

要求 \(r\)\(\operatorname{LIS}=b,\operatorname{LDS}=c\)

显然需要 \(b+c\le n+1\)

根据 Dilworth 定理,排列最多取成长为 \(c\)\(b\) 条反链,于是 \(bc\ge n\)

这也是充要条件。构造是简单的。

Subtask5 \(output=0\)

这提示我们判断是否有解的结论是很好猜的。

观察一下 \(a=1\) 时的限制: \(b+c\le n+1,bc\le n\)

\(a\) 硬凑进去,\(b+c\le n+a,abc\le n\)

实际上这就是正确的结论。先证明一下必要性:

考虑反证,假设 \(abc<n\)

\(\operatorname{LIS}(r)\le b\)

\(\operatorname{LIS}(q)=a\Rightarrow\operatorname{LDS}(q)\ge\frac{n}{a}\ge bc+1\)

\(\operatorname{LDS}(r)\le c\),否则任取出 \(q\) 一个长为 \(bc+1\) 的下降子序列会使得 \(\operatorname{LCS}(q,r)>c\)

考虑排列 \(r\),根据 Dilworth 定理有 \(bc\ge n\),矛盾。得证。

接下来用构造证明充分性。

正解(方案构造)

先不考虑 corner case,从 \(n=abc\) 这种细节较少的情况想起。

给出构造方案:

\(p=[1,2,\cdots,n]\)

\(q=[|n-a+1,n-a+2,\cdots,n|,|n-2a+1,n-2a+2,\cdots,n-a|,\cdots,|1,2,\cdots,a|]\)\(bc\) 个递减的长为 \(a\) 的递增块)

\(r=[|ac,ac-1,\cdots,1|,|2ac,2ac-1,\cdots,ac+1|,\cdots,|n,n-1,\cdots,n-ac+1|]\)\(b\) 个递增的长为 \(ac\) 的递减块)

\(\operatorname{LCS}(p,q)=a,\operatorname{LCS}(p,r)=b\) 都是显然的。

证明 \(\operatorname{LCS}(q,r)=c\)

首先有长为 \(c\) 的公共子序列 \((a-1)c+1,(a-2)c+1,\cdots,1\)

其次一定有 \(q,r\) 的公共子序列是递减的。在 \(q\) 中只有在同一个大小为 \(a\) 的块中能递增,\(r\) 中仍属于同一个块,要求递减。

于是只能在 \(r\) 中一个递减块中选,并且每 \(a\) 个在 \(q\) 中要求递增了,于是最多选 \(c\) 个。

这个构造必需的数是两两的公共子序列:\([1,2,\cdots,a],[1,ac+1,2ac+1,\cdots,(b-1)ac+1],[(a-1)c+1,(a-2)c+1,\cdots,1]\)

可以推广到所有 \(a+b+c-2\le n\) 的情况。具体只选择必需的数,不够再一直随便加数。

还剩下 \((a-1)+(b-1)+(c-1)\ge n\) 的情况需要讨论:

如果 \((n-1,a-1,b-1,c-1)\) 是合法的,在每个排列后面加入一个 \(n\) 就可以了。

所有 \((a-1)(b-1)(c-1)<n-1\) 的情况也被解决了。

把限制整理为 \(xyz\le x+y+z-2(x\le y\le z)\)

\(x>1\),有 \(xyz\ge4z>x+y+z>x+y+z+2\),于是 \(x=1\),代回原式为 \(yz\le y+z-1\)

\(y>1\),有 \(yz\ge2z\ge y+z>y+z-1\),于是 \(y=1\)

\(a\le b\le c\),有 \(a=2,b=2\)。代回限制得到 \(c=n-1\)

这种情况的构造很简单:\(p=[1,2,\cdots,n],q=[n,n-1,\cdots,4,3,1,2],r=[n,n-1,\cdots,4,1,3,2]\)

完工了。

代码

实现时可以用 set 来维护每个排列元素的顺序。

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
vector<int> p,q,r;
bool solve(int n,int a,int b,int c){
	if(b+c>a+n||1ll*a*b*c<n) return 0;
	if(!n) return 1;
	if(solve(n-1,a-1,b-1,c-1)){
		p.push_back(n);q.push_back(n);r.push_back(n);
		return 1;
	}
	if(a+b+c-2>n){
		for(int i=1;i<=n;i++) p.push_back(i);
		for(int i=1;i<=n-3;i++) q.push_back(n-i+1),r.push_back(n-i+1);
		q.insert(q.end(),{3,1,2});
		r.insert(r.end(),{1,3,2});
		return 1;
	}
	set<ll> sp;
	auto posq=[&](ll x) {return make_pair(-(x-1)/a,x);};
	auto cmpq=[&](ll x,ll y) {return posq(x)<posq(y);};
	set<ll,decltype(cmpq)> sq(cmpq);
	auto posr=[&](ll x) {return make_pair((x-1)/a/c,-x);};
	auto cmpr=[&](ll x,ll y) {return posr(x)<posr(y);};
	set<ll,decltype(cmpr)> sr(cmpr);
	auto add=[&](ll x) {sp.insert(x);sq.insert(x);sr.insert(x);};
	for(int i=1;i<=a;i++) add(i);
	for(int i=1;i<b;i++) add(1ll*i*a*c+1);
	for(int i=1;i<c;i++) add(1ll*i*a+1);
	for(int i=2,s=a+b+c-2;s<n;i++)
		if(!sp.count(i)) add(i),s++;
	map<ll,int> id;
	int t=0;
	for(ll x:sp) p.push_back(id[x]=++t);
	for(ll x:sq) q.push_back(id[x]);
	for(ll x:sr) r.push_back(id[x]);
	return 1;
}
int main(){
	int tot;scanf("%d",&tot);
	for(int n,a,b,c,op;tot--;){
		p.clear();q.clear();r.clear();
		scanf("%d%d%d%d%d",&n,&a,&b,&c,&op);
		if(solve(n,a,b,c)){
			puts("YES");
			if(!op) continue;
			for(int x:p) printf("%d ",x);
			puts("");
			for(int x:q) printf("%d ",x);
			puts("");
			for(int x:r) printf("%d ",x);
			puts("");
		}else puts("NO");
	}
	return 0;
}
posted @ 2022-10-09 23:17  shrtcl  阅读(165)  评论(0)    收藏  举报