Description
Input
Output
Sample Input
4 6 4 2 6 3 1 5 10 2 3 4 5 6 7 8 9 10 1 8 8 7 6 5 4 3 2 1 9 5 8 9 2 3 1 7 4 6
Sample Output
3 9 1 4
其实就是求最长上升子序列(LIS),由于长度太长,所以要用优化过的算法,复杂度降到了O(nlogn),dp[i]表示长度为i的LIS尾元素的最小值,当前获得的最大长度为len。若num[i]>dp[len],则dp[++len]=num[i],否则的话,注意到dp数组肯定是一个单调递增的数组,所以要找到一个j,使得dp[j]<num[i]<dp[j+1],再令dp[j+1]=num[i],查找可以使用二分,c++提供了upper_bound函数。这样最后的len就是所求答案。
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <map>
#include <vector>
#include <list>
#include <set>
#include <stack>
#include <queue>
#include <deque>
#include <algorithm>
#include <functional>
#include <iomanip>
#include <limits>
#include <new>
#include <utility>
#include <iterator>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <ctime>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
const double EPS = 1e-8;
const int MAXN = 1000010;
int dx[] = {0, 1, 0, -1}, dy[] = {-1, 0, 1, 0};
int main()
{
int T;
cin >> T;
while (T--)
{
int n, num, d[40010], len = 0;
cin >> n;
memset(d, 0, sizeof(d));
for (int i = 0; i < n; ++i)
{
scanf("%d", &num);
if (num > d[len])
d[++len] = num;
else
*upper_bound(d, d+len, num) = num;
}
cout << len << endl;
}
return 0;
}版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/god_weiyang/article/details/47658299