牛客挑战赛36 C 纸飞机 (最小链覆盖,LIS+思维,详细题解)
链接:https://ac.nowcoder.com/acm/contest/3782/C
来源:牛客网
纸飞机
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
直线上有n座山峰,第i座的高度为hi。从某座山峰上放飞一架纸飞机,它可以从左往右依次经过一系列高度严格递减的山头。
假设五座山峰的高度依次是3,4,3,2,1。从第一座山峰上放飞的纸飞机可以依次经过第一、四、五座山峰,但不能经过第二、三座山峰。
对于每座山峰,求出要经过除这座山峰外的每座山峰,至少需要放飞多少纸飞机。(每架纸飞机的起点可以不同)
输入描述:
第一行包括一个正整数n。第二行包括n个正整数,第i个数表示第i座山峰的高度hi。
输出描述:
输出一行,包括n个用空格隔开的正整数,第i个数表示除去第i座山峰的答案。
示例1
输入
复制
5
2 4 3 1 5
输出
复制
2 3 3 3 2
备注:
1≤n≤1061≤hi≤230
思路:
首先我们应该知道,最小链覆盖等于最长反链(反过来的最长不下降子序列)。
然后我们通过二分维护出以下两个数组:
\(f[i]\) 代表从左开始的以a[i] 结尾的 最长不下降子序列
$ b[i]$ 代表以a[i] 开始向右的最长不下降子序列
那么$ f[i]+b[i]-1 $ 就是包含a[i] 的 反向最长不下降子序列 长度
同时维护出最小链覆盖的值ans
那么删除a[i] 后的序列答案只有2种可能,ans 或 ans-1
如果a[i] 构成的反向最长不下降子序列 长度 是 ans,我们称之为腰点
1:如果a[i] 不是 腰点
那么删除后对序列的最小链覆盖没影响,所以答案是ans
2:如果a[i] 构成的反向最长不下降子序列 长度 是 ans
1) 当 所以腰点 中 a[i] 的 f[i] 只出现一次,那么a[i] 是构成的反向最长不下降子序列的核心点,删除之后会使答案-1,所以答案为ans-1
2) 当 所以腰点 中 a[i] 的 f[i] 出现多次,那么删除a[i] 后,会有其他 f[j]与f[i]相等的a[j]点代替掉a[i]的作用,所以答案仍为 ans
代码:
#include
#include
#include
#include
#include
#include
#include
#include