LIS的另一种简单做法nlogn(带路径)

来源:互联网 发布:荣威350软件 编辑:程序博客网 时间:2024/04/29 12:31

最长上升子序列(Longest Increasing Subsequence,LIS),在计算机科学上是指一个序列中最长的单调递增的子序列。

严格单调递增

第一种做法是离散化+树状数组/线段树,这种方法学了树状数组的人都能想得到。

第二种是二分+dp。小了个常数,时间和空间要稍稍比前面的快那么一些。

定义dp[i]=j,表示长度为i的上升自序列最小末端元素是j。

下面给出代码,不详细解释。


#include<algorithm>#include<cstdio>#include<cstring>#include<vector>using namespace std;const int maxn=1e5+7;int p[maxn];int n;int dp[maxn];int who[maxn];int pre[maxn];vector<int>path;int main(){    scanf("%d",&n);    for(int i=0;i<n;i++)scanf("%d",&p[i]);    memset(dp,0x7f,sizeof(dp));    int ans=0;    for(int i=0;i<n;i++)    {        int u=p[i];        int pos=lower_bound(dp+1,dp+1+n,u)-dp;        pre[i+1]=who[pos-1];////记录前面        dp[pos]=u;        who[pos]=i+1;/////更新位置        ans=max(pos,ans);    }    printf("%d\n",ans);    int now=who[ans];    while(now!=0)    {        path.push_back(now);        now=pre[now];    }    for(int i=path.size()-1;i>=0;i--)                printf("%d ",path[i]);    return 0;}


0 0
原创粉丝点击