最长递增子序列

来源:互联网 发布:举报网络传奇赌博 编辑:程序博客网 时间:2024/06/05 11:55

51NOD1134 最长递增子序列

n^2的算法:

n^2的算法就是两层循环,想法很简单:dp[i]记录的是长度到i的最大长度。
每次对dp[i]更新的时候,找到前面的数的最大dp[j](j < i)然后如果a[i] > a[j],就进行更新;

template<class T>int LIS(T a[],int n){int i,j;int ans=1;int m=0;int *dp=new int[n+1];dp[1]=1;for(i=2;i<=n;i++){m=0;for(j=1;j<i;j++){if(dp[j]>m&&a[j]<a[i])m=dp[j];}dp[i]=m+1;if(dp[i]>ans)ans=dp[i];}return ans;}

nlogn的算法:

维护一个一维数组dp,并且这个数组是动态扩展的,初始大小为1,dp[i]表示最长上升子序列长度是i的所有子串中末尾最小的那个数,根据这个数字,我们可以比较知道,只要当前考察的这个数比dp[i]大,那么当前这个数一定能通过c[i]构成一个长度为i+1的上升子序列。当然我们希望在dp数组中找一个尽量靠后的数字,这样我们得到的上升子串的长度最长,查找的时候使用二分搜索,这样时间复杂度便下降了
所以要进行二分找刚好大于a[i]的那个数在进行替换;

这里写图片描述

我的:

#include<iostream>#include<cstdio>#include<stdlib.h>#include<cmath>#include<string>#include<cstring>#include<map>#include<vector>#include<set>#include<algorithm>using namespace std;const int maxn=100000+5;int arr[maxn],ans[maxn];int len;int binary__search(int i){    int left=0,right=len,mid;    while(left<right)    {        mid=(left+right)/2;        if(ans[mid]>=arr[i])        {            right=mid;        }        else left=mid+1;    }    return left;}int main(){    int n;    while(~scanf("%d",&n))    {        for(int i=0;i<n;i++)        {            scanf("%d",&arr[i]);        }        ans[0]=arr[0];        len=0;        for(int i=1;i<n;i++)        {            if(arr[i]>ans[len])                ans[++len]=arr[i];            else            {//                int t=lower_bound(ans,ans+len,arr[i])-ans;//lower_bound(a,a+n,b)-a;二分函数返回的是一个有序的数列a中刚好大于给出的b的元素的地址               int t=binary__search(i);//或者自己编写二分函数                ans[t]=arr[i];            }        }        printf("%d\n",len+1);    }    return 0;}
0 0
原创粉丝点击