题意
给你一个长度为n的序列,求这个序列的最长上升子序列的长度
n<=100000
先说一下朴素的动态规划
即设(f[i])表示以(i)为结尾的,最长上升子序列的长度
状态转移
(if(a[j]<a[i]) f[i]=max(f[i],f[j]+1))
可以看出,朴素的动态规划我们的时间复杂度是(O(n^2))
时间复杂度肯定过不去,那么我们考虑怎么优化
不难发现,一个数会产生贡献,仅当它排在一个比它小的数后面,
我们可以开一个栈来维护
当这个新加进去的这个数比栈顶的元素小时,我们直接加进去
否则我们贪心的想,为了让其最长,小的数用的越多越好
所以我们就二分查找一下这个比较小的数可以放在哪里
将比它大的那个替换掉就好
时间复杂度(O(nlogn))
代码
#include<bits/stdc++.h>
using namespace std;
const int N=200000;
vector<int>arr(N);
int n,a[N];
int main()
{
cin>>n;
for(int i=1; i<=n; i++)
cin>>a[i];
arr.push_back(a[1]);
for(int i=2; i<=n; i++)
{
if(a[i]>arr.back())
arr.push_back(a[i]);
else {
*lower_bound(arr.begin(),arr.end(),a[i])=a[i];
}
}
cout<<arr.size()<<endl;
}
/*
例 n: 7
arr : 3 1 2 1 8 5 6
stk : 3
1 比 3 小
stk : 1
2 比 1 大
stk : 1 2
1 比 2 小
stk : 1 2
8 比 2 大
stk : 1 2 8
5 比 8 小
stk : 1 2 5
6 比 5 大
stk : 1 2 5 6
stk 的长度就是最长递增子序列的长度
*/