理论:动态规划初步--最长上升子序列(LIS)
模板:
void slove() { fill(dp, dp + n, INF); for (int i = 0; i < n; i++) { *lower_bound(dp, dp + n, a[i]) = a[i]; // *upper_bound(dp, dp + n, a[i]) = a[i]; // 非严格递增用upper_bound } int first = lower_bound(dp, dp + n, INF) - dp; printf("%d\n", dp[first - 1]); printf("%d\n", first); }
题解:相当于求最长公共子序列,但是普通的算法需要O(n*m)。
这道题目target数组是互异的,可以给它从1开始编号,拿这个编号规则再给arr编号。这样target已经是升序了,arr的LIS也就是原数组的最长公共子序列。
const int INF = 0x3f3f3f3f; class Solution { public: int minOperations(vector<int>& target, vector<int>& arr) { unordered_map<int, int>mp; int cnt = 0; for(int num : target) mp[num] = (++cnt); vector<int>myarr; for(int& num : arr) { if(mp[num]) myarr.push_back(mp[num]); } int n = arr.size(); vector<int>dp(n, INF); for(int num : myarr) { *lower_bound(dp.begin(), dp.end(), num) = num; } int lis = lower_bound(dp.begin(), dp.end(), INF)-dp.begin(); return target.size() - lis; } };