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