题目其实就是让你求LIS
但是因为题目中说了p<=40000
如果用O(n*n)的算法,必然超时
所以需要优化
看了下O(n*logn)的算法
解释如下:
先说下O(n*n)的算法:
用dp[i]保存以a[i]结尾的LIS最长长度
则对于当前的a[i],我们需要找到满足a[j]<a[i](j<i)且最大的dp[j]
则dp[i] = max(dp[i], dp[j]+1);
而优化就在于查找过程
用a数组保存给出的数据
用b[i]保存所有LIS长度为i-1的末尾最小元素值
则每次在b数组中二分查找满足条件的下标tmp
令b[tmp+1] = a[i]即可
代码如下:
#include <cstdio>
#define MAXN 40010
using namespace std;
int a[MAXN], b[MAXN];
int bin(int l, int r, int val) {
int m;
while(l <= r) {
m = (l+r) >> 1;
if(b[m] > val)
r = m-1;
else l = m+1;
}
return r;
}
int main(void) {
int T, n, tmp;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
for(int i=0; i<n; ++i)
scanf("%d", &a[i]);
int ans = 0;
b[0] = a[0];
for(int i=1; i<n; ++i) {
tmp = bin(0, ans, a[i])+1;//tmp:以a[i]结尾的LIS长度-1
b[tmp] = a[i];
//printf("b[%d] = a[%d] = %d\n", tmp, i, a[i]);
if(tmp > ans)
ans = tmp;//当前最长LIS长度-1
}
printf("%d\n", ans+1);
}
return 0;
}