单调递增子序列(二)
时间限制: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
解题:数据量大啊,o(n^2)方法不奏效啊!只有o(nlogn)算法了
先附上TLE代码吧1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <vector> 6 #include <climits> 7 #include <algorithm> 8 #include <cmath> 9 #define LL long long 10 using namespace std; 11 int d[100010],dp[100010]; 12 int main(){ 13 int n,i,j,ans; 14 while(~scanf("%d",&n)){ 15 for(i = 1; i <= n; i++){ 16 scanf("%d",d+i); 17 dp[i] = 1; 18 } 19 ans = 1; 20 for(i = 2; i <= n; i++){ 21 for(j = i-1; j; j--){ 22 if(d[j] < d[i] && dp[i] < dp[j]+1) dp[i] = dp[j]+1; 23 } 24 if(dp[i] > ans) ans = dp[i]; 25 } 26 printf("%d ",ans); 27 } 28 return 0; 29 }
好吧,上 AC 代码,O(nlogn)算法,精妙之处在于折半查找,速度很快的。噢最后那个top?top:1可以去掉的,秀逗了!损失4ms。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <vector> 6 #include <climits> 7 #include <algorithm> 8 #include <cmath> 9 #define LL long long 10 using namespace std; 11 int stk[100010],top; 12 void bsearch(int lt,int rt,int val) { 13 int mid; 14 while(lt <= rt) { 15 mid = (lt+rt)>>1; 16 if(val < stk[mid]) rt = mid-1; 17 else lt = mid+1; 18 } 19 stk[lt] = val; 20 } 21 int main() { 22 int n,i,temp; 23 while(~scanf("%d",&n)) { 24 top = 0; 25 for(i = 1; i <= n; i++) { 26 scanf("%d",&temp); 27 if(!top || stk[top-1] < temp) 28 stk[top++] = temp; 29 else bsearch(0,top-1,temp); 30 } 31 printf("%d ",top?top:1); 32 } 33 return 0; 34 }