题解:CF2124I Lexicographic Partition
这个题太厉害了!
首先第一步你要观察,如何写 spj,也就是根据已知排列求每个前缀的答案。先考虑整个排列
对于字典序最优这种问题,别无它法,必然是贪心。第一个数肯定是
这样就可以
这里我们不加证明的给出(其实直接理解即可),我们可以直接维护一个栈,表示目前的答案。每次加一个数时,就会弹一个后缀,把“在它之前第一个比它大的数到它的区间最小值之后的数”删掉。这样我们就可以很轻松的维护数据结构做到
回到正向构造部分。
注意到栈的结构十分特殊,因为每个时刻栈的大小都确定了,就为
根据这个结构,考虑加完
这启发我们,将
因为一个
考虑按一种方式来确定答案。因为点之间的顺序很明确,所以直接 dfs 确定。
可以定义 solve(x,l,r) 表示将确定
-
填最小的:儿子之间肯定是从左往右地递增去填(否则到第二个儿子的时候前面删不掉),因此划分区间的方案是固定的。只要前面
<x 的部分不捣乱即可。 -
填最大的:为了防止前面捣乱,相当于加了一个隔离挡板,后面的人删不到前面去,但是如果有多个儿子,就会出现删不掉的点,所以此时
x 只能有一个儿子。
什么时候会出事?连续两次都只能填最小的,也就是有一对父子同时有
引理:
证明是容易的,就根据我们之前那个模拟栈的思路,到
而如果存在
此时把这种情况排掉之后,就可以直接递归下去构造了,时间复杂度线性。
代码稍微有点写丑了,当时理解还不够深刻。大概思路和本文是相符的,凑合看看吧。