单调递增子序列(二)
时间限制:
1000 ms | 内存限制:
65535 KB
难度:
4
-
描述
-
给定一整型数列{a1,a2...,an}(0<n<=100000),找出单调递增最长子序列,并求出其长度。
如:1 9 10 5 11 2 13的最长单调递增子序列是1 9 10 11 13,长度为5。
-
输入
-
有多组测试数据(<=7)
每组测试数据的第一行是一个整数n表示序列中共有n个整数,随后的下一行里有n个整数,表示数列中的所有元素.每个整形数中间用空格间隔开(0<n<=100000)。
数据以EOF结束 。
输入数据保证合法(全为int型整数)!
输出
- 对于每组测试数据输出整形数列的最长递增子序列的长度,每个输出占一行。 样例输入
-
7 1 9 10 5 11 2 13 2 2 -1
样例输出
-
5 1
-
有多组测试数据(<=7)
解题思路:本题为典型的单调上升子序列问题, 当测试数据过多,容易超时, 进而,对其使用二分进行优化
AC代码:
# include <stdio.h>
# include <string.h>
# define M 100005
int num[M];
int dp[M];
int search(int num, int len)
{
int left = 1;
int right = len;
while (left <= right)
{
int mid = (left + right) / 2;
if (num > dp[mid])
{
left = mid + 1;
}
else
{
if (num < dp[mid])
{
right = mid - 1;
}
else
{
return mid; // 当num数组的值等于dp数组的值时,查找成功返回成功值
}
}
}
return left;
}
int main(void)
{
int n;
while (~scanf("%d", &n))
{
int i, k;
int count = 1;
memset(dp, 0, sizeof(dp));
for (i = 0; i < n; i++)
{
scanf("%d", &num[i]);
}
dp[0] = -100000000;
dp[1] = num[0];
for (i = 1; i < n; i++)
{
k = search(num[i], count);
dp[k] = num[i];
if (k > count)
{
count = k;
}
}
printf("%d\n", count);
}
return 0;
}