专栏文章
题解:CF2124I Lexicographic Partition
CF2124I题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minza6ki
- 此快照首次捕获于
- 2025/12/02 10:47 3 个月前
- 此快照最后确认于
- 2025/12/02 10:47 3 个月前
这个题太厉害了!
首先第一步你要观察,如何写 spj,也就是根据已知排列求每个前缀的答案。先考虑整个排列 的答案。
对于字典序最优这种问题,别无它法,必然是贪心。第一个数肯定是 ,下面想第二个。设最靠前的 的位置为 ,则如果 ,直接归约到 的答案;否则考虑 最大的为 ,将会归约到 的答案。
这样就可以 的算整个排列的答案了。但这还远远不够,想要优化,我们必须要换一种思路,从每次往后加一个数的角度入手。
这里我们不加证明的给出(其实直接理解即可),我们可以直接维护一个栈,表示目前的答案。每次加一个数时,就会弹一个后缀,把“在它之前第一个比它大的数到它的区间最小值之后的数”删掉。这样我们就可以很轻松的维护数据结构做到 check 了。
回到正向构造部分。
注意到栈的结构十分特殊,因为每个时刻栈的大小都确定了,就为 ,因此弹出多少个元素也是固定的。这就说明,栈里面的所有元素的坐标都是已知的(换句话说,我们知道任意时刻栈都由 构成, 是确定的)。
根据这个结构,考虑加完 后得到的栈 ,设倒数第二个元素为 (一定存在,因为 永远在栈中)。则 就是 填加 的结果。
这启发我们,将 向 连一条边,形成一棵树, 就是根结点 往 的路径顺次排列的结果。
因为一个 出现的时间是连续的(被删之后就再也不会复活了),因此它的子树对应的位置也是连续区间,也等价于这棵树的 dfn 序就是 。因此 如果不是叶节点,则 一定是 最靠左的儿子。
考虑按一种方式来确定答案。因为点之间的顺序很明确,所以直接 dfs 确定。
可以定义
solve(x,l,r) 表示将确定 的子树,填数范围在 中。根据直觉,我们要么填最小的数 ,要么填最大的数 。分别考虑对应的情况:-
填最小的:儿子之间肯定是从左往右地递增去填(否则到第二个儿子的时候前面删不掉),因此划分区间的方案是固定的。只要前面 的部分不捣乱即可。
-
填最大的:为了防止前面捣乱,相当于加了一个隔离挡板,后面的人删不到前面去,但是如果有多个儿子,就会出现删不掉的点,所以此时 只能有一个儿子。
什么时候会出事?连续两次都只能填最小的,也就是有一对父子同时有 个儿子。这里给一个充要的证明:
引理: 如果有不少于两个儿子,则对于其任意两个儿子,设左边的为 ,右边的为 ,则 。
证明是容易的,就根据我们之前那个模拟栈的思路,到 的时候 会作为最小值把后面的弹掉,而这些数都不能超过 ,于是就对了。
而如果存在 是 的儿子, 是 的儿子,且有 ,那从优化的角度上,没道理不删 ,所以就矛盾了。
此时把这种情况排掉之后,就可以直接递归下去构造了,时间复杂度线性。
代码稍微有点写丑了,当时理解还不够深刻。大概思路和本文是相符的,凑合看看吧。
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...