896 ac最长上升子序列

这个方法是nlogn的而动态规划是n方的

#include<bits/stdc++.h>
using namespace std;
vector<int> nums;
void help(vector<int>& arr, int n){
        //找到一个位置的数前面比n小自己比n大或者相等。
        int right = arr.size();
        int left = 1;
        int pos = 0;
        while (left <= right) {
            int mid = (right - left) / 2 + left;
            if (arr[mid] < n) {
                pos = mid;
                left = mid + 1;
            }            
            else {
                right = mid - 1;
            }
        }
        arr[pos + 1] = n;
    }
int lengthOfLIS(vector<int>& nums) {
        //维护一个数组记录最长递增子序列
        //然后每次遇到一个比数组最大的值小的数放进来修改里面的值
        //遇到比最大值大的就加入数组
        //遍历一遍是n 维护用二分法是logn 所以最后是nlogn
        vector<int> arr;
        int len = 1, n = nums.size();
        //为什么要从1开始,因为如果不从1开始 [pos + 1] 永远到不了0这个位置,
        //为了让当最小那个数字也比传进去那个数字大需要修改 arr[0](本来是这样)但是因为pos+1的情况到不了0 所以从1开始(那个
        //时候pos是0 加了1 就是1了
        if (n == 0) {
            return 0;
        }
        arr.push_back(-1);
        arr.push_back(nums[0]);
        for (int i = 1; i < n; i++) {
            if (nums[i] > arr[len]) {
                arr.push_back(nums[i]);
                len++;
            }
            else {
                help(arr, nums[i]);
            }
        }
        return len;
}
// 此方法说明 一个新员工一个老员工价值相当,老员工就可以走了,因为新员工被榨取的剩余空间更多。
int main() {
    int n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        int num;
        cin >> num;
        nums.push_back(num);
    }
    cout << lengthOfLIS(nums);
}
posted @ 2022-10-30 19:42  天然气之子  阅读(29)  评论(0编辑  收藏  举报