最长子序列问题

[NOIP1999] 导弹拦截

SOL1:

f i f_i fi 表示第 i i i 项结尾的 LDS 长度。

f i = max ⁡ j < i , a j ≥ a i f j + 1 f_i = \max_{j < i,a_j \ge a_i} f_j + 1 fi=j<i,ajaimaxfj+1

朴素做是 O ( n 2 ) O(n^2) O(n2) 的。代码。

显然可以 BIT 优化。代码。

SOL2:

f i f_i fi 表示长度为 i i i 的 LDS 中最后一项的最大值。 l e n len len 表示当前 LDS 长度。

对于元素 a i a_i ai,其可能产生以下贡献:

  • f l e n ≥ a i f_{len} \ge a_i flenai,可以贡献一个更长的 LDS。
  • f l e n < a i f_{len} < a_i flen<ai,找到 f f f 中第一个小于 a i a_i ai 的元素并替换。

代码

[SDOI2011] 拦截导弹

三维偏序的 LDS。详见我的博客 CDQ 分治。

iai 最长上升子序列

本题有三问:LIS 长度、可能在 LIS 的元素个数、一定在 LIS 的元素个数。前两问维护 i i i 的前后缀 LIS 即可。

第三问我们考虑反面,什么时候 i i i 不一定在 LIS 中。

SOL1:

构成 LIS 的元素的前缀连续增,后缀连续减。对于一个 “可能在” 的 i i i,若存在一个与其前后缀均相同的 j j j,那么 i i i 不一定在 LIS 中。容易维护某一对前后缀的出现次数。

代码

SOL2:

如果 LIS 的走线经过了 i , j i,j i,j,那么 [ i + 1 , j − 1 ] [i+1,j-1] [i+1,j1] 之间的元素肯定不是 “一定在” 。对于每个 “可能在” 的 i i i,找最远的 j j j,满足 a j > a i a_j > a_i aj>ai j j j 为最大后缀。特别的,我们需要考虑不存在这样的 j j j 的情况,可以通过在首尾增加无穷大和无穷小来实现。虽然后缀并不具有单调性,但 LIS 相同的元素后缀一定具有单调性,考虑对不同 LIS 长度建表后二分查找。

在这里插入图片描述

iai 最长上升子序列(二)

原题是 CF809D。

f i f_i fi 表示长度为 i i i 的 LIS 的最小结尾。

为保证保证 [ l i , r i ] [l_i,r_i] [li,ri] 中仅有一个数,可以将 l i l_i li r i r_i ri 间的数倒序构成新序列,此时的 LIS 即为最终答案。

先考虑最长不降子序列。对于新加入的区间 [ l , r ] [l,r] [l,r],对于 f f f 来说应将第一个大于 r r r 的数删去并插入 l l l,这个过程容易用 multiset 实现。

再考虑最长上升子序列。

你可能感兴趣的:(学习笔记,c++)