1802: 【提高】最长上升子序列LIS(2)
内存限制:128 MB
时间限制:1.000 S
评测方式:文本比较
命题人:
提交:5
解决:2
题目描述
给定一个长度为N的数列,求数值严格单调递增的子序列的长度最长是多少。
输入
第一行包含整数N。
第二行包含N个整数,表示完整序列。
1≤N≤100000,−109≤数列中的数≤109
第二行包含N个整数,表示完整序列。
1≤N≤100000,−109≤数列中的数≤109
输出
输出一个整数,表示最大长度。
样例输入 复制
6
1 3 2 8 5 6
样例输出 复制
4
提示
#include<bits/stdc++.h>
using namespace std;
//dp:长度为i的LIS的最后一位最小值是多少
int a[100100], dp[100100];
int i, n, l, r, mid;
int main() {
scanf("%d", & n);
for (i = 1; i <= n; i++) {
scanf("%d", & a[i]);
}
//边界
dp[1] = a[1];
int len = 1; //LIS 的长度
//从第2个数开始求解
for (i = 2; i <= n; i++) {
//如果 a[1]比 dp最后一位大,a[1]直接续上去,增加 LIS 的长度
if (a[i] > dp[len]) {
len++;
dp[len] = a[i];
} else {
//二分查找到dp数组中第1个>=a[1]的元素下标,普换(dp数组一定是递增的)
l = 1;
r = len;
while (l <= r) {
mid = (l + r) / 2;
if (a[i] <= dp[mid]) r = mid - 1;
else l = mid + 1;
}
//普换
dp[l] = a[i];
}
}
printf("%d", len);
return 0;
}