题目链接:POJ 1631 Bridging signals
【题意】简单来说就是求最长上升子序列的长度。
【思路】这道题目的数据规模有40000之多,如果用普通的动态规划O(n^2)肯定会超时的,所以要用上二分查找(又是二分啊,真牛逼)来进行优化,O(nlogn)的时间复杂度就OK了。
我使用了C++的lower_bound(ForwardIter first, ForwardIter last, const _Tp& val)函数.可以直接查找非递减序列[first, last)中的第一个大于等于值val的位置。
下面贴AC代码:
/*
** POJ 1631 Bridging signals
** Created by Rayn @@ 2014/05/06
** 最长上升子序列
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX = 40010;
int ans, arr[MAX], dp[MAX];
int main()
{
#ifdef _Rayn
freopen("in.txt", "r", stdin);
#endif
int t, n;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
for(int i=1; i<=n; ++i)
scanf("%d", &arr[i]);
memset(dp, 0, sizeof(dp));
ans = 0;
dp[ans++] = arr[1];
for(int i=2; i<=n; ++i)
{
if(arr[i] > dp[ans-1])
{
dp[ans++] = arr[i];
}
else
{
int *p = lower_bound(dp, dp+ans, arr[i]);
*p = arr[i];
}
}
printf("%d\n", ans);
}
return 0;
}