当前位置:首页 > 洛谷 > 洛谷P3902题解析:动态规划求解最长递增子序列(时间复杂度优化)

洛谷P3902题解析:动态规划求解最长递增子序列(时间复杂度优化)

6个月前 (09-03)

洛谷P3902题解析:动态规划求解最长递增子序列(时间复杂度优化) 洛谷题解 动态规划 C++ 二分查找 递增子序列 第1张

一、题目解读

洛谷P3902题要求给定一个整数序列,计算将其转换为最长递增子序列所需的最小修改次数。题目核心在于寻找原序列与最长递增子序列之间的差异,通过算法优化求解效率。理解“修改次数”即原序列长度与最长递增子序列长度的差值,成为解题的关键突破口。

二、解题思路

采用动态规划(DP)与二分查找的结合策略。传统LIS(最长递增子序列)问题通常使用O(n^2)的动态规划,但此处通过维护一个递增序列dp,利用lower_bound函数将时间复杂度降至O(nlogn)。核心思想是:每次遍历原序列元素时,找到dp中第一个大于等于该元素的位置,替换或扩展dp序列,最终dp的长度即为LIS长度。

三、解题步骤

1. 输入与初始化:读取序列n及元素,初始化动态规划数组dp为空。

2. 循环遍历:对每个元素num,通过二分查找找到dp中第一个不小于num的位置it。

3. 替换/扩展:

○ 若it为dp末尾(表示num大于所有现有元素),则扩展dp:dp.push_back(num)。

○ 否则替换it位置元素:*it = num(保证dp始终递增且长度最短)。

4. 输出结果:最终修改次数为n - dp.size(),即原序列长度减去LIS长度。

四、代码及注释

#include <bits/stdC++.h>
using namespace std;

const int MAXN = 1e5+5;

int main() {
    ios::sync_with_stdio(false); // 加快输入/输出速度
    cin.tie(0);
    
    int n;
    cin >> n; // 输入序列长度
    vector<int> nums(n); // 存储原序列
    for(int i=0; i<n; i++) {
        cin >> nums[i];
    }
    
    // 计算最长递增子序列长度
    vector<int> dp; // 动态规划数组,存储递增子序列
    for(int num : nums) {
        // 使用lower_bound找到第一个不小于当前元素的位置
        auto it = lower_bound(dp.begin(), dp.end(), num);
        if(it == dp.end()) { // 若num大于所有dp元素,扩展序列
            dp.push_back(num);
        } else { // 替换第一个不小于num的元素(缩短dp长度)
            *it = num;
        }
    }
    
    // 需要修改的次数 = 总长度 - 最长递增子序列长度
    cout << n - dp.size() << endl;
    return 0;
}

五、总结

本解法通过动态规划与二分查找的结合,巧妙地将LIS问题的时间复杂度优化至线性对数级别。关键在于维护递增序列dp并利用lower_bound精准定位替换位置,避免重复元素,从而高效计算修改次数。此思路对处理大规模数据的长递增子序列问题具有重要参考价值,同时为算法优化提供了实践范例。


原创内容 转载请注明出处

分享给朋友:

相关文章

力扣1137题:动态规划解泰波那契数 高效求解第N项的秘密

力扣1137题:动态规划解泰波那契数 高效求解第N项的秘密

一:重新解读题目泰波那契数列是一个充满数学趣味的递推序列:从第3项开始,每个数均为前三个数的和(即Tₙ₊₃ = Tₙ + Tₙ₊₁ + Tₙ₊₂)。当给定整数n时,需要高效计算出第n项的值。面对此类递...

牛客DP41精讲:当背包必须装满时,你的状态转移方程该如何调整?

牛客DP41精讲:当背包必须装满时,你的状态转移方程该如何调整?

题目重解我们面对一个经典背包问题的变体:给定n个物品,每个物品有重量w和价值v,背包容量为V。需要回答两个问题:1) 普通情况下能获得的最大价值;2) 必须恰好装满背包时的最大价值(若无法装满则输出0...

力扣933题:队列的妙用:如何高效统计最近请求

力扣933题:队列的妙用:如何高效统计最近请求

题目重解:我们需要设计一个能统计最近3000毫秒内请求次数的系统。每当新的请求到来时,它会带有时间戳t,我们需要返回过去3000毫秒内(包括当前)发生的请求总数。这就像是在时间轴上维护一个滑动窗口,只...

GESP2023年六级真题解析:动态规划解决小杨买饮料问题(洛谷3873)

GESP2023年六级真题解析:动态规划解决小杨买饮料问题(洛谷3873)

一、题目解读小杨买饮料是GESP 2023年六级认证考试中的一道经典动态规划题目,考察学生对背包问题的理解和应用能力。题目描述小杨需要购买n种饮料,每种饮料有特定的体积w和价格v,他要在不超过容量l的...

牛客12576题解题全解析:动态规划+质因数分解实现跳跃问题最优解

牛客12576题解题全解析:动态规划+质因数分解实现跳跃问题最优解

一、题目解读牛客12576题是一道经典的算法题,要求给定起点N和终点M,求解从N到M的最少跳跃次数。题目考察的核心在于路径优化与动态规划思想,需结合数论中的质因数分解技巧,通过合理设计算法降低时间复杂...

NOIP 2008火柴棒等式题解(C++代码实现)  动态规划与枚举算法详解

NOIP 2008火柴棒等式题解(C++代码实现) 动态规划与枚举算法详解

一、题目解读火柴棒等式问题(NOIP 2008,洛谷P1149)要求使用给定数量的火柴棒,构造形如 A + B = C 的等式,其中A、B、C均为整数,且火柴棒总数恰好等于输入值。需统计符合条件的等式...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。