首页 > 代码库 > 51nod 1134 最长递增子序列
51nod 1134 最长递增子序列
给出长度为N的数组,找出这个数组的最长递增子序列。(递增子序列是指,子序列的元素是递增的)
例如:5 1 6 8 2 4 5 10,最长递增子序列是1 2 4 5 10。
Input
第1行:1个数N,N为序列的长度(2 <= N <= 50000)
第2 - N + 1行:每行1个数,对应序列的元素(-10^9 <= S[i] <= 10^9)
Output
输出最长递增子序列的长度。
Input示例
8
5
1
6
8
2
4
5
10
Output示例
5
//第一种做法,放入一个数然后更新
#include <iostream> #include <stdio.h> #include <string.h> using namespace std; long long a[100000],b[100000]; int main(){ int n; while(cin>>n){ memset(a,1000000009,sizeof(a)); memset(b,1000000009,sizeof(b)); int i,j; for(i=0;i<n;i++) cin>>a[i]; int x=0; for(i=0;i<n;i++){ for(j=0;j<n;j++){ if(a[i]<b[j]){ //每次放入一个数,找到适当的位置更新 b[j]=a[i]; if(j>x) x=j; break; //因为一个数只用一次更新,所以循环结束 } } } cout<<x+1<<endl; } return 0; }
//第二种runtime ……额 ……┭┮﹏┭┮……等我不这么菜了,再改
建立一个辅助数组c[n],c[i]储存的是子序列长度为i的序列最后一值即
子序列长度为i有多个,但是要求最后一个值最小,
比如 1, 4,7,3,8,2,1
1,4
1,3
1,2
1,1
从前往后遍历数组a[n],处理a[i-1]时,观察c数组,每个a数组中的值和
c数组中的值进行比较,找到合适的位置插入(若插入到c数组的末尾,那么
所求最长上升子序列长度+1,恩,,你应该隐约感受到了什么了吧,不错呢c数组的
长度就是最后我们所要求滴,撤回来),否则就替换掉c数组原来位置上的值
这有助于我们通过a数组计算b数组(b[i]中保存的是以a[i]为最后一个元素的
最长单调递增子序列) 若a[i]<a[j],就b[j]赋值b[i] c中药保存a[i]
由于c数组下标代表子序列长度,c数组中的值也是按递增序列排序,所以很符合二分
#include <iostream> using namespace std; int find(int *a,int len,int n){ //二分find int l=0,r=len,mid=(l+r)>>1; while(l<=r){ if(n>a[mid]) l=mid+1; else if(n<a[mid]) r=mid-1; else return mid; mid=(l+r)>>1; } } void init(int *a,int n){ for(int i=0;i<=n;i++) a[i]=1000; } int main(){ int maxn,i,j,n,a[100],b[100],c[100]; while(cin>>n){ init(c,n+1); for(i=0;i<n;i++) cin>>a[i]; c[0]=-1; //天然最小值 c[1]=a[0]; //initialization b[0]=1; //b[i]表示以a[i]结尾的最长单调递增子序列 for(i=1;i<n;i++){ //复杂度是N j=find(c,n+1,a[i]); //复杂度logN的 c[j]=a[i]; b[i]=j; } for(maxn=i=0;i<n;i++) //遍历一遍找到最大值 if(b[i]>maxn) maxn=b[i]; cout<<maxn<<endl; } return 0; }
51nod 1134 最长递增子序列
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。