翻译题解不易,求大家轻喷。
首先考虑(a=b=n)的情况。
显然(2)操作所移动的数必须是单增的并且应该与(s3)的前面连接上,并且如果(s2)的前缀符合这样的条件,那么我们应当立即执行(2)操作将它们转移过去。所以我们将(2)操作称为输出,每次操作后都应检查一下是否有机会输出,如果有机会则立即执行输出。类似的,对于(1)操作我们也有类似的限制,但要复杂得多:
首先,当(s2)中存在两个数(x,y)满足(y)恰好在(x)前面一位且(y<x-1)时不可能有合法方案,因为无法将([x,y])之间的元素移进来,我们将这样的情景称为死胡同。
如果一个序列由若干个部分组成,每一段数都是连续的单调递增的自然数,并且后一段所有数都比前一段小,那么我们称这个序列是好的,它大概形如(x_1,x_1+1,x_1+2,dots,y_1,x_2,x_2+1,dots,y_2,x_3,dots),并且满足(x_1>y_2,x_2>y_3,dots)。考虑(s1)中最长的好前缀,显然将这个前缀移到(s_2)的过程中不能一起移它后面的元素,否则会形成死胡同。移一部分到(s2)就进行输出也是不可能,因此我们一定会将这个前缀通过若干次(1)操作后整个移动到(s2)再执行其他操作。
那么唯一的问题就是如何移动这个前缀了,我们分情况讨论:
- 如果这个前缀中出现的所有数是连续的,也就是说(y_2=x_1-1,y_3=x_2-1,dots),那么我们可以将各个部分依次移动到(s2)中形成一个单增的段,在适当的时间可以直接整段进行输出。序列的内部一定不会出现死胡同,只可能(y_1)与(s2)此时的开头产生死胡同,即当前(s2)的第一位(>y_1+1),那么我们无论怎么移都会出现这个死胡同,因此我们只需要考虑用依次移动的方法能否成功。
- 否则,我们唯一的选择是将整个前缀整体移动过去。证明的话,设(x_k>y_{k+1}+1)最终将前缀分成若干段进行移动,如果没有任何一段同时包含了(y_k)与(x_{k+1}),那么(y_k)所在的段会与(x_{k+1})的段形成死胡同,否则,这一段一定会与前面后面的段都产生死胡同。
因此,我们可以通过(mathcal O(n^2))的每次找到最长的好前缀进行移动并判断能否进行输出来完成任务,因为我们始终采取最优策略,所以如果最终没有成功移走所有飞机那么一定没有答案。
当(a)与(b)( ot=n)时,输出不一定总是合法的,但如果每次可以执行输出时都立即执行,出现无法执行的输出就一定意味着失败,因此我们依然假设所有输出都可以执行,出现了不可执行的就说明没有答案。
依然检查最长的好前缀:
- 如果前缀中出现的数并不连续,那么我们依然只能整段进行移动,如果其长度(>a)则没有答案。
- 否则,因为每次移动的长度很重要,所以一段一段移动不一定最优,我们需要继续进行恶心的分类讨论:
- 如果每一段的长度都(le a)且前缀的总长度(le b),依然采用之前的策略是最优的。
- 考虑前缀总长度(>b)的情况:
- 如果前缀由单独的一段组成,在输出时如果我们希望这一段与其他段一起输出,那么必然要求移动后(y1)在最底部或者(x1)在最顶部,而这是不可能完成的,因此我们只能选择在自己输出不与其他数扯上关系,而采取一个一个输入(s2)变成降序排列再依次输出确保了这一点能够完成,是最优选择。
- 如果前缀由(>2)段组成,那么只能依次整体移动每一段,否则总意味着死胡同,然后再看能不能输出。
- 如果前缀由(2)段组成,只有两种可行方案:先移动第一段的前面一部分再移动其他部分,或者先移动第一段和第二段的前面一部分再移动其他部分(都是移动两次),根据移动长度(le a)的限制,我们容易列出一些不等式,又因为输出这一前缀时也不可能带上其他部分,所以任何满足不等式条件的移动方式的一样优,任取一个即可。
- 如果前缀总长度(le b)但存在某一段长度(>a):
- 如果前缀由单独的一段组成,一个一个移。
- 由两个以上段组成,没有合法方案
- 由两段组成,类似地列出一些不等式找合法方案。
我们同样可以得到以这样的操作方案进行操作,最后无法成功一定意味着没有答案的结论。因此我们(mathcal O(n^2))的模拟操作即可。