题意:
找出个数组成的序列的最长单调递增子序列。
朴素分析:
状态表示: 表示从第一个数字开始,以结尾的最长的上升序列。
状态计算:
在,有
时间复杂度
朴素代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
int n, ans;
int a[N], f[N];
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i ++)
scanf("%d", &a[i]);
ans = 1;
for (int i = 1; i <= n; i ++) {
f[i] = 1;
for (int j = 1; j < i; j ++) {
if (a[i] > a[j])
f[i] = max(f[i], f[j] + 1);
}
ans = max(ans, f[i]);
}
printf("%d", ans);
return 0;
}
优化分析:
状态表示: 表示长度的最长上升子序列,末尾最小的数字。
状态计算:
如果 则 使得最长上升序列长度+1,当前末尾最小元素为
如果 则说明不会更新当前的长度,但当前的变化会使未来的更长的长度更优,找到第一个 大于或等于 以更新
时间复杂度
优化代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
int n, len;
int a[N], f[N];
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i ++)
scanf("%d", &a[i]);
f[++ len] = a[1];
for (int i = 2; i <= n; i ++) {
if (a[i] > f[len]) {
f[++ len] = a[i];
} else {
int l = 1, r = len;
while(l < r) {
int mid = l + r >> 1;
if (f[mid] >= a[i])
r = mid;
else
l = mid + 1;
}
f[r] = a[i];
}
}
printf("%d", len);
return 0;
}
Q.E.D.