1 条题解

  • 0
    @ 2026-9-3 10:46:13

    题解

    思路

    1. 拆分单个位置的贡献

    固定位置 ii,令 pip_i 为 ii 右侧最后一个满足 api>aia_{p_i}>a_i 的位置;若不存在则记为无效。

    一个包含位置 ii 的递增子序列会让 ii 贡献 11,当且仅当该子序列的末尾位置严格小于 pip_i。因此位置 ii 的总贡献可以拆成:

    1. 以 ii 结尾的递增子序列数 LiL_i;
    2. 从 ii 开始、且最后位置小于 pip_i 的递增延伸数 GiG_i(允许不再选择元素)。

    二者可以任意拼接,故答案为

    ∑iLiGi(mod109+7).\sum_i L_iG_i\pmod {10^9+7}.

    做法

    子任务 1:枚举子序列

    当 n≤18n\le18 时枚举所有非空下标集合,检查是否严格递增。设末尾为 rr,再求 rr 后方最大值,逐个判断所选元素是否产生贡献。复杂度为 O(2nn)O(2^n n)。

    子任务 2:二次动态规划

    先计算不限制末尾的后缀方案数

    Fi=1+∑j>i, aj>aiFj.F_i=1+\sum_{j>i,\ a_j>a_i}F_j.

    若 pip_i 存在,则 pip_i 后方所有数都不大于 aia_i。对 i<j<pii<j<p_i:

    • 若 aj≥apia_j\ge a_{p_i},从 jj 出发的任何严格递增延伸都不可能选择 pip_i 或其后位置,可以直接加入 FjF_j;
    • 若 ai<aj<apia_i<a_j<a_{p_i},则 pj=pip_j=p_i,应加入已经计算的 GjG_j。

    再计入“不继续选择”的一种方案,有

    $$G_i=1+ \sum_{\substack{i<j<p_i\\a_j\ge a_{p_i}}}F_j+ \sum_{\substack{i<j<p_i\\a_i<a_j<a_{p_i}}}G_j.$$

    倒序直接枚举转移即可做到 O(n2)O(n^2)。

    子任务 3:非递增序列

    严格递增子序列只能取一个元素,而其右侧不存在更大的值,所以所有权值均为 00。

    满分算法

    将数值离散化。LiL_i 是标准的递增子序列计数,可从左到右用树状数组维护值域前缀和:

    Li=1+∑j<i, aj<aiLj.L_i=1+\sum_{j<i,\ a_j<a_i}L_j.

    倒序计算 Fi,GiF_i,G_i 时维护两棵树状数组:

    • 第一棵按值维护所有已处理位置的 FF,并在比所有离散值都大的哨兵处放入 11,代表空延伸;
    • 第二棵按值维护已经求出的 GG。

    于是

    Fi=∑v>aiBITF(v),F_i=\sum_{v>a_i}\mathrm{BIT}_F(v),

    并且当 pip_i 存在时

    $$G_i= \sum_{v\ge a_{p_i}}\mathrm{BIT}_F(v)-F_{p_i} +\sum_{a_i<v<a_{p_i}}\mathrm{BIT}_G(v).$$

    第一项中的哨兵自动给出空延伸;减去 FpiF_{p_i} 正好排除选取 pip_i 的方案。pip_i 可用后缀最大值二分,或倒序以值域最大位置数据结构求得。

    复杂度

    枚举算法为 O(2nn)O(2^n n),二次动态规划为 O(n2)O(n^2),非递增支线为 O(n)O(n)。满分算法对每个测试用例的时间复杂度为 O(nlog⁡n)O(n\log n),空间复杂度为 O(n)O(n);多测时将 nn 换成所有测试用例规模之和。

    • 1

    信息

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