AGC043D Merge Triplets
题意 : 将
用如下算法生成一个排列
- 找出栈顶最小的(非空)栈,将栈顶加到
的末尾,并弹栈。
问有多少排列
我们发现这和归并排序类似,唯一的不同之处在于各个小序列初始时可能是无序的。
这给我们一种感觉:排列
显然,若各个栈初始时有序,则排列
不难发现,若栈中有一段数
而且,相邻两段“连续弹出”的第一次弹出是递增的。
于是,原序列被划分为了若干长度为
观察栈中连续头大段的组成:
又能发现,
若满足上述两个条件,必然能构造出对应方案。
构造:对于所有
自成一栈。 对于
其中 ,选出任一个 与其配对成栈。 若
则可以配成 ,若 则可以配成 ,总能配对。 对于剩余的
,三个分别排序后成一栈。
找出了充要条件,(根据数据范围)接下来使用 DP。
先考虑若已经确定段的分布,填数的方案数。约束等价为:对于段
把每个段翻转,则变为要求
证明 : 考虑归纳,对于满足前
记
转移时枚举下一段为
为了方便,可以将
复杂度为