当前位置:首页 > 洛谷 > 洛谷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精准定位替换位置,避免重复元素,从而高效计算修改次数。此思路对处理大规模数据的长递增子序列问题具有重要参考价值,同时为算法优化提供了实践范例。


原创内容 转载请注明出处

分享给朋友:

相关文章

力扣第1991题:寻找数组的中心索引 如何找到左右和相等的中心索引

力扣第1991题:寻找数组的中心索引 如何找到左右和相等的中心索引

题目解读给定一个整数数组,我们需要找到一个中心索引,使得该索引左侧所有元素的和等于右侧所有元素的和。如果不存在这样的索引,则返回-1。中心索引的定义不包含在左右两侧的和计算中。这个问题考察对数组遍历和...

NOIP2005 普及组 洛谷P1408 背包问题的空间优化技巧与实战应用

NOIP2005 普及组 洛谷P1408 背包问题的空间优化技巧与实战应用

题目重解想象你是一名药师,有t分钟在山上采集m种草药。每种草药需要time分钟采集,价值为num。这就像考试时分配时间做题,要选择收益最大的题目组合。题目要求计算在规定时间内能获得的最大草药价值。解题...

CSP-J 2019纪念品题解(洛谷P5662):动态规划+完全背包问题的实战应用

CSP-J 2019纪念品题解(洛谷P5662):动态规划+完全背包问题的实战应用

一、题目解读2019年CSP-J的“纪念品”问题(对应洛谷P5662)要求玩家在T天内通过买卖纪念品最大化金币收益。每天可交易N种商品,需计算最优策略下的最终金币数。题目强调动态规划思维与资源分配优化...

CSP-J方格取数题解|动态规划解法|洛谷P7074代码解析

CSP-J方格取数题解|动态规划解法|洛谷P7074代码解析

一、题目解读题目要求在一个n×m的网格中,从左上角到右下角选择一条路径,路径上的数字可重复取用,求取数之和的最大值。路径限制为仅能向右或向下移动。需注意路径的灵活性与重复取数的可能性,传统单向动态规划...

2024蓝桥杯省赛B组“传送阵”题解(C++代码+图论算法优化)

2024蓝桥杯省赛B组“传送阵”题解(C++代码+图论算法优化)

一、题目解读2024年蓝桥杯省B组“传送阵”题目要求处理一个包含n个节点的图,节点间存在单向传输关系。每个节点i可传送至a[i]指定的节点,形成可能存在的环结构。题目需求解从任意节点出发能到达的最长路...

1999年NOIP提高组导弹拦截(洛谷P1020)解题思路与动态规划代码解析

1999年NOIP提高组导弹拦截(洛谷P1020)解题思路与动态规划代码解析

一、题目解读    1999年NOIP提高组“导弹拦截”问题(对应洛谷P1020)要求设计导弹拦截系统:给定一组导弹高度数据,需计算最少拦截系统数量,并求最多能...

发表评论

访客

看不清,换一张

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