刚开始做这题的时候,以为是简单的动态规划,后来提交之后发现超时了,看到了N可以达到100000,用简单的动态规划,时间复杂度达到了N^2,明显会超时。
想了挺久的,还是不知道怎么做,百度了一下,才知道了原来运用二分搜索,把问题简化成类似排序,时间复杂度为logN,就不会超时了。
下面是AC的代码,看注释可以很容易理解的。如说的有错,欢迎指正。
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
int a[100005], dp[100005];
int binarysearch(int num, int len) //二分搜索,搜索a数组每个数应该放在dp数组的哪个位置,将位置返回
{ //普通的二分搜索,很容易理解的
int left, right, mid;
left = 1;
right = len;
mid = (left + right) / 2;
while(left <= right)
{
if(dp[mid] == num) //该数num在递增序列的中间的情况
return mid;
else if(dp[mid] > num)
right = mid - 1;
else
left = mid + 1;
mid = (left + right) / 2;
}
return left; //插到数组dp的最后,也就是递增序列的最后,递增序列加1
}
int main()
{
int n, i, j;
while(cin >> n)
{
for(i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
memset(dp, 0, sizeof(dp));
int len = 1;
dp[1] = a[0]; //先放一个数进dp数组
for(i = 1; i < n; i++) //将剩下的a数组中的数一个一个的找到相应的位置
{
j = binarysearch(a[i], len); //返回相应的位置
dp[j] = a[i]; //将a【i】赋值过去
if(j > len) //如果该位置j比len大,赋值给len
len = j;
}
cout << len << endl;
}
return 0;
}