题目描述 Description
LIS问题是最经典的动态规划基础问题之一。如果要求一个满足一定条件的最长上升子序列,你还能解决吗?
给出一个长度为N整数序列,请求出它的包含第K个元素的最长上升子序列。
例如:对于长度为6的序列<2,7,3,4,8,5>,它的最长上升子序列为<2,3,4,5>,但如果限制一定要包含第2个元素,那么满足此要求的最长上升子序列就只能是<2,7,8>了。
输入描述 Input Description
第一行为两个整数N,K,如上所述。(80%的数据,满足0<n<=1000,0<k<=n ; 100%的数据,满足0<n<=200000,0<k<=n)
接下来是N个整数,描述一个序列。
输出描述 Output Description
请输出两个整数,即包含第K个元素的最长上升子序列长度。
样例输入 Sample Input
8 6
65 158 170 299 300 155 207 389
样例输出 Sample Output
4
代码
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; inline int read() { int num = 0 , f = 1; char ch = getchar(); while (!isdigit(ch)) { if (ch == ‘-‘) f = -1; ch = getchar(); } while (isdigit(ch)) { num = num * 10 + ch - ‘0‘; ch = getchar(); } return num * f; } int n,k,cnt,len = 1; int temp[200010],line[200010],f[200010],End[200010]; void Binary_Search() { for (int i = 2; i <= n; i++) { int index = 0; int left = 1 , right = len; do { int mid = (left + right) / 2; if (End[mid] < line[i]) { left = mid + 1; index = mid; } else right = mid - 1; }while (left <= right); f[i] = index + 1; if (f[i] > len) len = f[i]; End[f[i]] = line[i]; } } int main() { n = read(); k = read(); for (int i = 1; i <= n; i++) line[i] = read(); for (int i = 1; i < k; i++) if (line[i] < line[k]) temp[++cnt] = line[i]; temp[++cnt] = line[k]; for (int i = k + 1; i <= n; i++) if (line[i] > line[k]) temp[++cnt] = line[i]; n = cnt; for (int i = 1; i <= n; i++) line[i] = temp[i]; End[1] = line[1]; f[1] = 1; Binary_Search(); printf("%d",len); return 0; }