当前位置:首页 > 洛谷题解 > 洛谷P3902题解:最长递增子序列的贪心优化

洛谷P3902题解:最长递增子序列的贪心优化

16小时前洛谷题解38

截图未命名.jpg 洛谷P3902题解:最长递增子序列的贪心优化 洛谷题解 动态规划 二分查找 贪心算法 C++ 分治思想 第1张

一、问题背景

洛谷P3902题目要求计算使序列变为严格递增序列所需的最小修改次数。通过转化为最长递增子序列问题,我们可以高效解决这一难题。

二、算法核心思想

  1. 问题转化:最小修改次数 = 序列长度 - 最长递增子序列长度

  2. 贪心优化:使用二分查找维护可能的最优序列

  3. 时间复杂度:O(n log n),相比传统DP的O(n²)大幅优化

三、完整代码实现(带详细注释)

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

const int MAXN = 1e5+5; // 定义最大数组长度

int main() {
    ios::sync_with_stdio(false); // 加速输入输出
    cin.tie(0); // 解除cin与cout的绑定
    
    int n;
    cin >> n;
    vector<int> nums(n);
    for(int i=0; i<n; i++) {
        cin >> nums[i]; // 读取输入序列
    }
    
    // 计算最长递增子序列长度
    vector<int> dp; // 维护的可能LIS序列
    for(int num : nums) {
        // 使用lower_bound找到第一个不小于当前元素的位置
        auto it = lower_bound(dp.begin(), dp.end(), num);
        if(it == dp.end()) {
            dp.push_back(num); // 当前元素大于所有元素,扩展序列
        } else {
            *it = num; // 替换第一个不小于当前元素的元素
        }
    }
    
    // 输出需要修改的次数
    cout << n - dp.size() << endl;
    return 0;
}

四、关键步骤解析

  1. lower_bound函数:在有序序列中二分查找插入位置

  2. 维护dp数组:始终保持dp数组的递增性和最小末尾元素

  3. 替换策略:用更小的元素替换原有元素,为后续元素创造更多可能

五、学习建议

  1. 先理解传统DP解法

  2. 手动模拟小规模数据

  3. 尝试实现其他LIS变种问题

  4. 练习相关题目巩固理解


原创内容 转载请注明出处

分享给朋友:

发表评论

访客

看不清,换一张

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