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

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

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


原创内容 转载请注明出处

分享给朋友:

相关文章

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

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

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

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

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

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

手搓顺序表类代码注释与详解:从零实现动态数组(新手教程)

一、简介和特点顺序表(Sequential List)是数据结构中基础的一种线性表,其特点是将数据元素存储在连续的内存空间中。通过数组实现,支持随机访问(即通过索引直接访问元素),适用于频繁随机读取的...

洛谷P4551题解题报告:图论与Trie树优化异或路径问题的实战解析

洛谷P4551题解题报告:图论与Trie树优化异或路径问题的实战解析

一、题目解读洛谷P4551题要求在一个无向图中,寻找任意两点路径权值异或后的最大值。题目输入为图的边信息(点数n和n-1条边),每条边包含起点、终点及权值。需输出所有路径中权值异或的最大值。问题核心在...

CSP-J 2019公交换乘题解析:基于队列优化的动态规划代码详解

CSP-J 2019公交换乘题解析:基于队列优化的动态规划代码详解

一、题目解读CSP-J 2019年的“公交换乘”题目(洛谷P5661)要求模拟地铁与公交交替出行的费用计算。题目核心在于地铁消费会产生优惠券,而公交可在45分钟内使用优惠券抵扣车费。需要处理n条出行记...

洛谷2789题解:直线交点数的递归求解与优化(附代码详解)

洛谷2789题解:直线交点数的递归求解与优化(附代码详解)

一、题目解读洛谷2789题要求计算n条直线在平面上两两相交时产生的不同交点数量。题目强调“不同”交点,需排除重复情况。解题关键在于如何高效枚举所有可能的交点组合,并避免重复计数。二、解题思路参考代码采...

发表评论

访客

看不清,换一张

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