dp最长上升子序列(单调队列优化)
给定一个长度为N的数列,求数值严格单调递增的子序列的长度最长是多少。(N <= 1e5)
朴素做法时间复杂度O(n^2)过不了
用单调队列的思想优化可以O(nlongn)
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int Ull;
const ll N = 1e5+10;
int arr[N];
int main(){
//ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0);
//用单调队列的思想,V[i]的位置存长度为i的递增序列最后一个数的最小值
//可知,V 是递增的。
//遍历原数组,若arr[i]大于队尾元素则入队列(说明当前维护的最长序列长度可以加一),
//否则就用arr[i]替换V中第一个大于等于arr[i]的值(若该值是V[j],说明V[j-1]严格小于arr[i],V[j]大于等于arr[i],
//则j长度的递增序列的最后一个数更新为arr[i])
//lower_bound用二分的方法从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end
int n;
cin>>n;
for(int i = 1; i <= n; i++) cin>>arr[i];
vector<int> V;
for(int i = 1; i <= n; i++){
if(V.size() == 0) V.push_back(arr[i]);
else{
if(arr[i] > V.back()) V.push_back(arr[i]);
else *lower_bound(V.begin(),V.end(),arr[i]) = arr[i];
}
}
cout<<V.size()<<endl;
}

浙公网安备 33010602011771号