题目描述 Description
LIS问题是最经典的动态规划基础问题之一。如果要求一个满足一定条件的最长上升子序列,你还能解决吗?
给出一个长度为N整数序列,请求出它的包含第K个元素的最长上升子序列。
例如:对于长度为6的序列<2,7,3,4,8,5>,它的最长上升子序列为<2,3,4,5>,但如果限制一定要包含第2个元素,那么满足此要求的最长上升子序列就只能是<2,7,8>了。
输入描述 Input Description
第一行为两个整数N,K,如上所述。
接下来是N个整数,描述一个序列。
输出描述 Output Description
请输出两个整数,即包含第K个元素的最长上升子序列长度。
样例输入 Sample Input
8 6
65 158 170 299 300 155 207 389
样例输出 Sample Output
4
数据范围及提示 Data Size & Hint
80%的数据,满足
100%的数据,满足
题解
首先,要求最长上升子序列中必须有第K个,那么K前面的比K大的元素一定不在所求子序列中,K后面比K小的也不在。所以预处理:先把K前面的比K大的元素和K后面比K小的元素全部删去,这样K一定在新序列的最长上升子序列中。然后在新得到的序列上做
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 200010;
int n, k, a[maxn], b[maxn], tot;
int s[maxn], top;
void init()
{
int x = 0;
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
for(int i = 1; i < k; ++i)
{
if(a[i] < a[k]) b[++tot] = a[i];
}
b[++tot] = a[k];
for(int i = k + 1; i <= n; ++i)
{
if(a[i] > a[k]) b[++tot] = a[i];
}
}
void work()
{
for(int i = 1; i <= tot; ++i)
{
if(b[i] > s[top]) s[++top] = b[i];
else
{
int l = 1, r = top, mid;
while(l <= r)
{
mid = (l >> 1) + (r >> 1) + (l & r & 1);
if(s[mid] < b[i]) l = mid + 1;
else r = mid - 1;
}
s[l] = b[i];
}
}
printf("%d", top);
}
int main()
{
init();
work();
return 0;
}
@echo off
:loop
rand.exe > data.txt
Codevs2188.exe < data.txt > std.txt
Codevs2188最长上升子序列.exe < data.txt > ans.txt
fc /A std.txt ans.txt
if not errorlevel 1 goto loop
pause
:end
原文地址:http://blog.csdn.net/t14t41t/article/details/46364625