版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39562952/article/details/81332783
思路:
最长上升子序列(LIS)的典型变形,熟悉的n^2的动归会超时。LIS问题可以优化为nlogn的算法。
定义d[k]:长度为k的上升子序列的最末元素,若有多个长度为k的上升子序列,则记录最小的那个最末元素。
注意d中元素是单调递增的,下面要用到这个性质。
首先len = 1,d[1] = a[1],然后对a[i]:若a[i]>d[len],那么len++,d[len] = a[i];
否则,我们要从d[1]到d[len-1]中找到一个j,满足d[j-1]<a[i]<d[j],则根据D的定义,我们需要更新长度为j的上升子序列的最末元素(使之为最小的)即 d[j] = a[i];
最终答案就是len
利用d的单调性,在查找j的时候可以二分查找,从而时间复杂度为nlogn。
https://blog.csdn.net/shuangde800/article/details/7474903
代码如下:
#include<iostream>
#include<algorithm>
#include<cstring>
#define maxn 200000+100
using namespace std;
int b[maxn];
int main()
{
int n;
int t,ans;
while (cin >> n)
{
ans = 0;
memset(b, 0, sizeof(b));
b[0] =-1;
ans++;
for (int i = 0; i < n; i++)
{
cin >> t;
if (t >= b[ans - 1])
{
b[ans++] = t;
}
else
{
int z = upper_bound(b, b + ans, t)-b;
b[z] = t;
}
}
cout << ans-1 << endl;
}
return 0;
}