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);
}