1 条题解

  • 0
    @ 2026-4-4 16:01:58

    题目重述

    称一个整数序列是美丽的,如果满足:

    • 除第一个元素外,每个元素左边都存在一个比它小的元素;
    • 除最后一个元素外,每个元素右边都存在一个比它大的元素。

    给定数组 aa,求最长美丽子序列的长度。


    性质转化

    美丽序列的定义等价于:

    序列的第一个元素是唯一的最小值,最后一个元素是唯一的最大值

    原因:

    • 第一个元素左边没有元素,所以它必须是整个序列的最小值(否则它左边无法有比它小的元素)。
    • 最后一个元素右边没有元素,所以它必须是整个序列的最大值(否则它右边无法有比它大的元素)。
    • 中间元素满足左右各有比它小和比它大的元素,自然可以满足条件。

    因此,问题转化为:在数组 aa 中找最长子序列,使得第一个元素是子序列的最小值(且唯一),最后一个元素是子序列的最大值(且唯一)。


    二维平面转化

    将每个元素 aia_i 视为平面上的点 (i,ai)(i, a_i)

    一个美丽子序列对应一个矩形:
    设子序列的第一个元素下标为 ii,最后一个元素下标为 jji<ji < j),且 ai<aja_i < a_j(否则无法成为最小和最大)。
    那么子序列可以包含所有满足 ipji \le p \le jai<ap<aja_i < a_p < a_j 的点吗?
    实际上,我们可以在矩形内自由选择中间的点,只要保持单调性要求即可。

    关键观察
    如果我们固定左下角 (i,ai)(i, a_i) 和右上角 (j,aj)(j, a_j),那么所有严格位于矩形内部的点 (p,ap)(p, a_p) 满足 i<p<ji < p < jai<ap<aja_i < a_p < a_j。这些点可以任意排列成美丽子序列(按原顺序),而两端 (i,ai)(i, a_i)(j,aj)(j, a_j) 恰好是最小和最大。
    所以,ii 为起点、jj 为终点的美丽子序列的最大长度等于矩形内部点数 +2+ 2(包含两端)。

    因此问题变成:找两个点 (i,ai)(i, a_i)(j,aj)(j, a_j)i<j,ai<aji < j, a_i < a_j),使得矩形 (i,ai)(i, a_i)(j,aj)(j, a_j) 内部包含尽可能多的点。


    优化起点和终点

    起点优化

    如果存在 i<ii' < iaiaia_{i'} \le a_i,那么以 ii' 为起点的矩形可以包含以 ii 为起点的矩形(因为 ii' 更左,aia_{i'} 更小或相等,矩形更大),所以答案不会更差。
    因此我们只需要考虑前缀最小值点ii 满足对所有 i<ii' < i,有 ai>aia_{i'} > a_i
    这些点满足:下标递增,值严格递减。记这些点为 leftleft 数组。

    终点优化

    对称地,只需要考虑后缀最大值点jj 满足对所有 j>jj' > j,有 aj<aja_{j'} < a_j
    这些点满足:下标递增,值严格递增。


    矩形匹配

    对于任意点 xx(作为候选终点),哪些 leftleft 中的点可以作为它的左下角?
    需要满足:

    1. 下标 i<xi < x(否则不是左下角)
    2. ai<axa_i < a_x(否则不能是最小值)

    由于 leftleft 下标递增、值递减,所以满足 ai<axa_i < a_xiileftleft 中一个前缀,满足下标 i<xi < x 的是另一个前缀。
    取交集,得到 leftleft 中连续的一段区间 [lf,rg)[\text{lf}, \text{rg}),其中:

    • lf\text{lf} 是第一个满足 aleft[lf]<axa_{\text{left}[\text{lf}]} < a_x 的位置
    • rg\text{rg} 是第一个满足 left[rg]x\text{left}[\text{rg}] \ge x 的位置

    这两个边界都可以用二分查找在 O(logn)O(\log n) 时间内得到。


    算法流程

    我们考虑从右到左枚举终点 jj(只枚举后缀最大值点)。
    维护一个数据结构,对于每个 leftleft 中的起点 ii,记录当前有多少个已加入的点位于矩形 (i,ai)(i, a_i) 到当前终点 jj 的内部。

    当我们从 jj 移动到下一个更左的终点 jj'j<jj' < j)时:

    • 新加入的终点 jj' 值更大(因为后缀最大值递增),所以需要把值介于 aja_jaja_{j'} 之间的点加入数据结构。
    • 同时,下标在 [j,j)[j', j) 之间的点被排除(因为新的矩形左边界右移了,这些点不再在内部)。

    每个点只会被加入一次、删除一次,所以总操作次数 O(n)O(n)

    数据结构需要支持:

    • 区间加(给某个起点对应的所有矩形内部点数加 11 或减 11
    • 查询全局最大值

    这可以用线段树维护区间加和区间最大值。


    最终答案

    对于每个候选终点 jj,查询 leftleft 中区间 [lfj,rgj)[\text{lf}_j, \text{rg}_j) 的最大值,记为 mm
    则该终点对应的最长美丽子序列长度为 m+1m + 1(加上终点自身)。
    注意:如果区间为空,则只能单独取该点,长度为 11

    取所有候选终点的最大值即为答案。

    时间复杂度:O(nlogn)O(n \log n)

    • 1

    信息

    ID
    6355
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者